父进程创建N个子节点,每个子节点用exec替换自己。父和exec之间通过一系列管道进行通信( int pipefd [N] [2]; )
exec 使用以下命令写入管道:
char msg[50];
sprintf( msg, "\tsent from pid: %d, pi= %f", getpid(), pi);
printf("%s\n",msg);
write(i1, msg, strlen(msg)+1);
,父母用以下内容阅读:
for (i=0;i<N;i++) {
close(pipefd[i][1]); // close the write end of the pipe in the parent
read(pipefd[i][0], buffer, sizeof(buffer));
printf("\n-C-\n");
if (buffer[0] == '\t'){
printf("%s\n",buffer);
}
int j;
for (j=0; j<100; j++) {
buffer[j]='\n';
}
close(pipefd[i][0]);
}
现在问题是,在子节点终止后,仅读取被解除阻塞并打印缓冲区。 我想要做的是在exec写入管道后立即打印缓冲区。
以下是所有代码:
父文件:
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#define N 5
pid_t *pid;
int pipefd[N][2];
int flag = 0;
int count_ctrl_c = 0;
void signal_handler(int sig){
signal(sig, SIG_IGN);
printf("\n");
flag = 1;
signal(SIGINT, signal_handler);
}
int main(int argc, char *argv[]) {
int i;
for (i = 0; i < N; i++) {
pipe(pipefd[i]);
}
int parent_pid = getpid();
pid= (pid_t *)malloc(N * sizeof(pid_t));
for (i = 0; i < N; i++) {
pid[i] = fork();
if (pid[i] == 0) //The parent process will keep looping
{
char b[50];
sprintf( b, "%d", i+1);
char i0[50];
sprintf( i0, "%d", pipefd[i][0]);
char i1[50];
sprintf( i1, "%d", pipefd[i][1]);
char par_id[50];
sprintf( par_id, "%d", parent_pid);
execl("***the/path/to/exec/calculate***", b,i0,i1,par_id,NULL);
}
}
if (parent_pid == getpid()) {
signal(SIGINT, signal_handler);
while(1){
if (flag){
printf("\n-A-\n");
char buffer[100];
int i;
for (i=0;i<N;i++) {
// Apostellei to shma SIGUSR2 se ola ta paidia tou
kill(pid[i], SIGUSR2);
}
printf("\n-B-\n");
for (i=0;i<N;i++) {
close(pipefd[i][1]); // close the write end of the pipe in the parent
read(pipefd[i][0], buffer, sizeof(buffer));
printf("\n-C-\n");
if (buffer[0] == '\t'){
printf("%s\n",buffer);
}
int j;
for (j=0; j<100; j++) {
buffer[j]='\n';
}
close(pipefd[i][0]);
}
//exit(0);
printf("finished reading\n");
flag = 0;
count_ctrl_c++;
if (count_ctrl_c == 2) {
exit(0);
}
}
}
}
}
calculate.c
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#define N 5
int i0,i1,parent_pid;
int flag = 0;
int time_to_term = 0;
double pi;
void signal_handler2(int sig);
void signal_handler(int sig);
void signal_handler2(int sig){
signal(sig, SIG_IGN);
signal(SIGALRM, SIG_IGN);
flag = 1;
signal(SIGUSR2, signal_handler2);
signal(SIGALRM, signal_handler);
}
void signal_handler(int sig){
signal(sig, SIG_IGN);
pid_t pid = getpid();
printf("time: %d, pid: %d, pi: %1.10f\n", time_to_term, pid, pi);
exit(0);
}
int main(int argc, char *argv[]) {
int pid;
signal(SIGINT, SIG_IGN);
signal(SIGUSR2, signal_handler2);
signal(SIGALRM, signal_handler);
time_to_term = atoi(argv[0]);
alarm(time_to_term);
i0 = atoi(argv[1]);
i1 = atoi(argv[2]);
parent_pid = atoi(argv[3]);
double mul = 1.0;
double par = 2.0;
pi = 3.0;
while(1){
pi = pi + (mul * (4.0 / (par * (par + 1.0) * (par + 2.0))));
mul = mul * (-1.0);
par += 2;
sleep(1);
if (flag) {
signal(SIGALRM, SIG_IGN);
close(i0);
char msg[50];
sprintf( msg, "\tsent from pid: %d, pi= %f", getpid(), pi);
printf("%s\n",msg);
write(i1, msg, strlen(msg)+1);
close(i1);
flag = 0;
signal(SIGALRM, signal_handler);
//exit(0);
}
}
}
答案 0 :(得分:1)
对此进行故障排除的一般提示:使用strace
工具运行管道的两侧(您可以使用strace -f
跟踪分支),以便您可以验证从管道实际写入/读取的内容
我怀疑在这种情况下,孩子没有写任何东西!这是因为您使用的stdio图层( printf())会检查它是写入终端还是其他任何内容。对于终端,它会在每个换行符后刷新输出,但在其他情况下,只有在写入大量数据块(GNU系统上为8KiB)后才会刷新。尝试在 printf()之后使用 fflush()手动刷新输出。如果这有帮助,您可以使用 setvbuf()调整 stdout 缓冲模式。
答案 1 :(得分:1)
在父流程中:
dup
fd的#0和#1保留供父进程以后使用;在这些新fd上使用fcntl
和F_DUPFD_CLOEXEC
来阻止exec
上的继承
close
fd#0
close
fd#1
创建管道
阻止继承上述管道的读取fd
dup2
写入管道的fd使其成为fd#1; close
原始写作fd
fork
&amp; exec
子进程
为所有必要的孩子重复步骤3到7
dup2
将原始fd的#0和#1的重复项存回#0和#1以恢复printf
/ scaf
功能
使用select
轮询读取所有管道的fd,如果期望在#0
如果需要进行双向通信,则在步骤4创建两个管道,并对所描述的过程进行适当调整,并重复步骤2到7以创建子项。
在子进程中(exec
之后)
根据需要进行所有处理。使用fd#1或printf或其他任何内容写入父级。
子进程可能始终使用PID
getppid()
答案 2 :(得分:0)
您的操作系统可能正在缓冲写入。
在调用ioctl
后,尝试使用FLUSHW
和write
显式刷新管道。此外,检查您的返回值,以防发生隐藏的事情。有关ioctl
的更多信息,请参阅http://pubs.opengroup.org/onlinepubs/7908799/xsh/ioctl.html。