Я пишу программу для выполнения другой программы в виде разветвленного процесса и перенаправляю ее вывод в файл или/dev/null по требованию.C - перенаправление stdout после разворачивания дочернего элемента из родителя
В настоящее время я разветвил и выполнил внешнюю программу с помощью execvp(). Затем перенаправил stdout из потока, созданного до разветвления, так как разветвленный процесс наследует родительскую таблицу дескриптора файла, позволяющую мне перенаправить после вымывания.
Но, я могу изначально перенаправить stdout в желаемый файл, и оба родителя и дочерние stdouts перенаправляются. Однако, если я попытаюсь перенаправить его еще раз в другой файл, только родительский stdout будет перенаправлен, дочерний stdout останется прежним.
Вот код без битов проверки ошибок.
struct params {
const char *p;
int fd;
int wait;
};
#define EXIT_NOEXEC 126
#define EXIT_NOTFOUND 127
#define EXIT_MISC 127
static void dofile(struct params* st);
void dupit(const char *p, struct params* st);
void* reload_config(void* para);
int
main(int argc, char *argv[]) {
int exit_status, prog_status;
struct params init;
pid_t prog_pid;
dofile(&init);
prog_pid = fork();
if (prog_pid == 0) {
execvp(*argv, argv);
exit_status = (errno == ENOENT) ? EXIT_NOTFOUND : EXIT_NOEXEC;
err(exit_status, "%s", argv[0]);
exit(EXIT_FAILURE);
} else {
while (wait(&prog_status) != prog_pid);
return prog_status;
}
}
static void dofile(struct params* st) {
const char *p
p = out.txt;
dupit(p, st);
}
void dupit(const char *p, struct params* st) {
pthread_t tid;
st->wait = 0;
int err = pthread_create(&(tid), NULL, &reload_config, st);
if (err != 0) {
printf("\ncan't create thread :[%s]", strerror(err));
exit(1);
} else {
while (st->wait == 0) {
sleep(1)
}
}
}
void* reload_config(void* para) {
struct params *passed = (struct params *) para;
int pre_config = 3;
int cur_config = 1;
int saved_stdout = dup(STDOUT_FILENO);
char infile[5];
int devNull = open("/dev/null", O_WRONLY);
int file = open("out.txt", O_WRONLY);
FILE *config;
config = fopen("config.txt", "r");
if (access("config.txt", F_OK) != -1) {
while (1) {
fgets(infile, 5, config);
fclose(config);
cur_config = infile[0] - '0';
printf("output from thread, current config = %d\n", cur_config);
if (pre_config != cur_config) {
if (cur_config == 1) {
if (dup2(file, STDOUT_FILENO) == -1) {
err(EXIT_MISC, NULL);
}
} else {
dup2(devNull, STDOUT_FILENO);
}
pre_config = cur_config;
}
if (passed->wait==0) {
passed->wait = 1;
}
sleep(1);
}
} else {
if (dup2(passed->fd, STDOUT_FILENO) == -1) {
err(EXIT_MISC, NULL);
}
}
}
Ну, я немного изменил код, чтобы вы, ребята, поняли, поэтому некоторые части не имеют смысла. Но вы получаете основную идею.
Как я могу перенаправить детское stdout как пожелаю после форкирования.
AFAIK, процесс не может напрямую изменять потоки другого процесса. Родительскому процессу необходимо будет использовать механизм IPC, чтобы сообщить дочернему процессу, для чего перенаправляется новый файл, а сам процесс-потомк должен выполнить перенаправление. – kaylum
Но начальное перенаправление работает, что означает, что ребенок действительно унаследовал родительскую таблицу fd. Но для меня непонятно, после первого звонка я не могу перенаправить выступление ребенка. – ivcode
Это было * перед тем * вилка. То есть в то время был только один процесс. Как только вилка выполнена, есть два процесса, которые имеют одинаковые дескрипторы файлов. Но с этого момента они независимы. То есть вы можете настроить дескрипторы файлов, как вам нравится, прежде чем вилка и дочерний процесс после запуска получат эти дескрипторы файлов - точно так, как вы описали. Но родитель не может изменить дескрипторы дочерних файлов после вилки. – kaylum