Linux从文件中读取奇怪的行为

我试图创build一个程序,创build一个文件,写入0,然后,使用subprocess,交替增加该值。 例如,孩子应该将该值增加到1,并将其写回文件。 之后,父母将其增加到2并将其写入文件中。 孩子要3,等等。 过程之间的同步通过信号完成。 这里是源代码:

#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> void sig_hand (int sig); int fd; int main() { pid_t pid; int i; fd = open ("abc.txt",O_RDWR|O_TRUNC); if (fd == -1) { fd = creat ("abc.txt",S_IRUSR|S_IWUSR); } write (fd,"0",2); if ((pid = fork()) < 0) { fprintf (stderr, "Error creating process\n"); exit (1); } else { if (pid == 0) { signal (SIGUSR1,sig_hand); for (;;) { pause(); kill (getppid(),SIGUSR1); } } if (pid > 0) { sleep (1); signal (SIGUSR1,sig_hand); for (i=0;i<5;i++) { kill (pid,SIGUSR1); pause (); } kill (pid,SIGTERM); } } return 0; } void sig_hand (int sig) { int x; char c; read (fd,&c,2); x=atoi(&c); x++; printf ("x=%d\n",x); snprintf (&c,3,"%d",x); lseek (fd,0,SEEK_SET); printf ("PID %d is writing\n",getpid()); write (fd,&c,2); } 

运行这个程序产生以下输出:

 x=1 PID 4434 is writing x=1 PID 4433 is writing x=2 PID 4434 is writing x=2 PID 4433 is writing x=3 PID 4434 is writing x=3 PID 4433 is writing x=4 PID 4434 is writing x=4 PID 4433 is writing x=5 PID 4434 is writing x=5 PID 4433 is writing 

为什么孩子和父母在一次迭代中递增相同的值?

谢谢!

你的主要问题是你不能用这种方式来计时。 每当我运行它,你的程序就会陷入僵局。 一个程序可以(通常会)发送信号,然后另一个可以等待。 你完全依赖于调度器,你不能预测或预测它。 所以正确的程序是阻止信号,所以它是不会交付,直到你准备好处理它。 下面的程序使用sigrocmasksigsuspend来完成。

你的第二个问题是克里斯·J·基里克(Chris J. 您正在读取和写入1个字节的内存位置2个字节但更重要的是,文件描述符是在父母和孩子之间共享的,所以您需要每次都寻找到正确的位置,否则其他进程会将它放在您不知道的地方不要期待。

 #define _POSIX_C_SOURCE 1 #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) void sig_hand(int sig); int fd; int main() { pid_t pid; int i; if ((fd = open("abc.txt", O_RDWR | O_TRUNC)) == -1) errExit("open"); struct sigaction sa; sigset_t saveMask, blockMask; //block SIGUSR1 sigemptyset(&blockMask); sigaddset(&blockMask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &blockMask, &saveMask) == -1) errExit("sigprocmask"); //set up signal handler (both parent & child) sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sig_hand; if (sigaction(SIGUSR1, &sa, NULL) == -1) errExit("sigaction"); if (write (fd, "\0", sizeof(char)) == -1) errExit("initial write"); if ((pid = fork()) < 0) errExit("fork"); if (pid == 0) { for (;;) { if (sigsuspend(&saveMask) == -1 && errno != EINTR) errExit("sigsuspend"); kill(getppid(), SIGUSR1); } } if (pid > 0) { for (i = 0;i < 5;i++) { kill(pid, SIGUSR1); if (sigsuspend(&saveMask) == -1 && errno != EINTR) errExit("sigsuspend"); } kill(pid, SIGTERM); } return 0; } void sig_hand(int sig) { char c; if (lseek(fd, 0, SEEK_SET) == (off_t) - 1) errExit("lseek"); if (read(fd, &c, sizeof(char)) == -1) errExit("read"); c++; printf("c = %d\n", c); if (lseek(fd, 0, SEEK_SET) == (off_t) - 1) errExit("lseek"); printf("PID %d is writing\n", getpid()); if (write (fd, &c, sizeof(char)) == -1) errExit("write"); } 

问题不是你的同步,而是你的文件访问。 您从文件中读取,回溯到开头,然后写入文件。 你认为下一个阅读是从哪里来的? 每次写入之后,您都需要回到文件的开头。

您也有一些缓冲区溢出,因为您使用一个字符作为单个字符的字符串。 它不会这样工作,因为你没有空终止符。

这是一个更正的sig_hand

 void sig_hand (int sig) { int x; char c[3]; read (fd,c,2); x=atoi(c); x++; printf ("x=%d\n",x); snprintf (c,3,"%d",x); lseek (fd,0,SEEK_SET); printf ("PID %d is writing\n",getpid()); write (fd,c,2); lseek (fd,0,SEEK_SET); }