我正在编写一个程序来执行另一个程序作为分叉进程,并根据需要将其输出重定向到文件或/ dev / null.
目前我已经使用execvp()分叉并执行了外部程序.
然后从分叉之前创建的线程重定向stdout,因为分叉进程将继承父文件描述符表,允许我在foking之后重定向.
但是,我最初可以将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);
}
}
}
好吧,我改变了一些代码,所以你们会理解,所以有些部分没有意义.但是你得到了基本的想法.
如何在分叉后按照我的意愿重定向孩子的标准输出.
最佳答案 既然你问过,这里有一个简单的例子.为简洁起见,我们采取了一些捷径,但希望它会给你一些想法.该程序打开file1并将stdout重定向到该文件.它然后做一个分叉.子进程每1秒向stdout(通过printf)写一个计数器.几秒钟之后,父进程使用IPC(本例中的管道)告诉子进程切换重定向文件.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv)
{
pid_t pid;
const char *file1 = "file1.txt";
const char *file2 = "file2.txt";
int pipefd[2];
int fd;
int rval;
fd = open(file1, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
if (fd == -1) {
perror("file1 open");
exit(-1);
}
/*
* This pipe will be used by parent process to tell child which file
* to redirect to.
*/
rval = pipe2(pipefd, O_NONBLOCK);
if (fd == -1) {
perror("pipe");
exit(-1);
}
/* Redirect stdout to the file opened before the fork. */
dup2(fd, STDOUT_FILENO);
pid = fork();
if (pid == -1) {
perror("fork");
exit(-1);
} else if (pid == 0) {
/* Child process. */
int ix;
char redirect_file[100];
close(pipefd[1]);
for (ix = 0; ix < 10; ix++) {
printf("%d\n", ix);
sleep(1);
rval = read(pipefd[0], redirect_file, sizeof(redirect_file));
if (rval > 0) {
/*
* Parent process has written a filename to the pipe.
*/
fd = open(redirect_file, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
if (fd == -1) {
perror("file2 open");
exit(-1);
}
/* Ensure previous output has been written to current file. */
fflush(stdout);
/* Change redirect now. */
dup2(fd, STDOUT_FILENO);
}
}
} else {
/* Parent process. */
close(pipefd[0]);
/* Wait a little and then tell child to change redirect file. */
sleep(5);
write(pipefd[1], file2, strlen(file2) + 1);
wait();
}
}
如果运行此程序,您会发现子输出的一半转到file1(第一次重定向),另一半输出转到file2(第二次重定向).
$cat file1.txt
0
1
2
3
4
$cat file2.txt
5
6
7
8
9
最后一点说明.示例程序在fork之前执行第一个dup.我是这样做的,因为这是你的代码的显示方式,也是为了强调问题的前后方面.但在实际代码中,传统的做法是首先执行fork,然后执行dup,最后执行exec.在fork之后完成dup,这样只有子进程受到影响而不是父进程(除非那真的是你想要的).