C Linux从文件读取异常行为
我试图创建一个程序,创建一个文件,将0写入其中,然后使用子进程交替递增该值。例如,子级应将该值增加到1,并将其写回文件。在此之后,父级将其增量为2,并将其写入文件中。这孩子要3岁,依此类推。进程之间的同步通过信号完成。以下是源代码:C Linux从文件读取异常行为,c,linux,unix,signals,C,Linux,Unix,Signals,我试图创建一个程序,创建一个文件,将0写入其中,然后使用子进程交替递增该值。例如,子级应将该值增加到1,并将其写回文件。在此之后,父级将其增量为2,并将其写入文件中。这孩子要3岁,依此类推。进程之间的同步通过信号完成。以下是源代码: #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> void
#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);
}
为什么子代和父代在一次迭代中递增相同的值
谢谢 问题不在于同步,而在于文件访问。从文件中读取内容,返回到开头,然后写入文件。你认为下一次阅读会从哪里来?您还需要在每次写入后查找回文件的开头
您还存在一些缓冲区溢出,因为您将字符用作单个字符串。它不是那样工作的,因为您没有空终止符的空间。问题不在于您的同步,而在于您的文件访问。从文件中读取内容,返回到开头,然后写入文件。你认为下一次阅读会从哪里来?您还需要在每次写入后查找回文件的开头
您还存在一些缓冲区溢出,因为您将字符用作单个字符串。它不能那样工作,因为你没有空终止符的空间。你的主要问题是你不能用那种方式对信号计时。你的程序第一次死机,每次我运行它。一个程序可以(通常会)在另一个程序等待信号之前发送信号。您完全依赖于调度程序,无法预测或预测它。因此,正确的程序是阻止信号,以便在您准备好处理它之前不会发送信号。下面的程序使用
sigrocmask
和sigssuspend
来实现这一点
你的第二个问题就是被提到的问题。您正在从一个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");
}
\define\u POSIX\u C\u源代码1
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义errExit(msg)do{perror(msg);exit(exit_FAILURE);}while(0)
无效信号(内部信号);
int-fd;
int main()
{
pid_t pid;
int i;
如果((fd=open(“abc.txt”,O|RDWR | O|TRUNC))=-1)
退出(“开放”);
struct-sigaction-sa;
sigset\u t saveMask,blockMask;
//块SIGUSR1
SIGEPTYSET(和块掩码);
sigaddset(和块掩码,SIGUSR1);
if(sigprocmask(SIG_块、块掩码和保存掩码)=-1)
errExit(“sigprocmask”);
//设置信号处理程序(父级和子级)
sigemptyset(和sa.sa_面具);
sa.sa_标志=0;
sa.sa_handler=sig_hand;
if(sigaction(SIGUSR1,&sa,NULL)=-1)
errExit(“sigaction”);
如果(写入(fd,“\0”,sizeof(char))=-1)
errExit(“初始写入”);
如果((pid=fork())<0)
退出(“fork”);
如果(pid==0)
{
对于(;;)
{
如果(SIGSSUSPEND(&saveMask)=-1&&errno!=EINTR)
errExit(“sigsuspend”);
kill(getppid(),SIGUSR1);
}
}
如果(pid>0)
{
对于(i=0;i<5;i++)
{
kill(pid,SIGUSR1);
如果(SIGSSUSPEND(&saveMask)=-1&&errno!=EINTR)
errExit(“sigsuspend”);
}
kill(pid,SIGTERM);
}
返回0;
}
无效信号手(内部信号)
{
字符c;
if(lseek(fd,0,SEEK_SET)==(off_t)-1)
errExit(“lseek”);
if(读取(fd,&c,sizeof(char))=-1)
退出(“读取”);
C++;
printf(“c=%d\n”,c);
if(lseek(fd,0,SEEK_SET)==(off_t)-1)
errExit(“lseek”);
printf(“PID%d正在写入\n”,getpid());
if(写入(fd,&c,sizeof(char))=-1)
退出(“写入”);
}
您的主要问题是无法以这种方式对信号计时。你的程序第一次死机,每次我运行它。一个程序可以(通常会)在另一个程序等待信号之前发送信号。您完全依赖于调度程序,无法预测或预测它。因此,正确的程序是阻止信号,以便在您准备好处理它之前不会发送信号。下面的程序使用sigrocmask
和sigssuspend
来实现这一点
你的第二个问题就是被提到的问题。您正在从一个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");
}
\define\u POSIX\u C\u源代码1
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义errExit(msg)do{perror(msg);exit(exit_FAILURE);}while(0)
无效信号(内部信号);
int-fd;
int main()
{
pid_t pid;
int i;
如果((fd=open(“abc.txt”,O|RDWR | O|TRUNC))=-1)
退出(“开放”);
struct-sigaction-sa;
sigset\u t saveMask,blockMask;
//块SIGUSR1
SIGEPTYSET(和块掩码);
sigaddset(和块掩码,SIGUSR1);
if(sigprocmask(SIG_块、块掩码和保存掩码)=-1)
errExit(“sigprocmask”);
//设置信号处理程序(父级和子级)
sigemptyset(和sa.sa_面具);
sa.sa_标志=0;
sa.sa_handler=sig_hand;
if(sigaction(SIGUSR1,&sa,NULL)=-1)
errExit(“sigaction”);
如果(写入(fd,“\0”,sizeof(char))=-1)
errExit(“初始写入”);
如果((pid=fork())<0)
退出(“fork”);
如果(pid==0)
{
对于(;;)
{
如果(SIGSSUSPEND(&saveMask)=-1&&e
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);
}