我需要使用Signal在C中编写UNIX进程间通信程序。我希望父进程和子进程写入同一个文件。 结果只显示父文字。我可以使用BSD或System V.请帮助
#include <stdio.h> /* basic I/O routines. */
#include <unistd.h> /* define fork(), etc. */
#include <sys/types.h> /* define pid_t, etc. */
#include <sys/wait.h> /* define wait(), etc. */
#include <signal.h>
int myFlag = 0;
void myHandler(int);
int child_pid;
int main()
{
//oldmask = sigblock(sigmask(SIGUSR1));
sighold(SIGUSR1);
sighold(SIGINT);
/* critical region */
signal (SIGUSR1, myHandler);
sigrelse(SIGUSR1);
sigrelse(SIGINT);
child_pid = fork();
if (child_pid==0) {
for ( ; ; ) {
while(myFlag == 0)
sigpause(0);
sigblock (sigmask(SIGUSR1));
myFlag = 0;
FILE *fp=fopen("test","w");
fwrite("child",1,6,fp);
fclose(fp);
kill(getppid(),SIGUSR1);
}
}
if (child_pid>0){
FILE *fp;
fp=fopen("test","w");
fwrite("parent",1,6,fp);
fclose(fp);
for ( ; ; ) {
while(myFlag == 0)
sigpause(0);
sigblock (sigmask(SIGUSR1));
myFlag = 0;
fp=fopen("test","w");
fwrite("parent",1,6,fp);
fclose(fp);
}
kill(child_pid, SIGUSR1);
//kill ()-child_pid ;
}
exit(0);
}
void myHandler(int sigNo) {
myFlag = 1;
//signal (SIGUSR1, myHandler);
}
答案 0 :(得分:1)
您应该首先以追加模式而不是写模式打开文件:
fp = fopen("test", "a");
这会将fp
的写入位置定位在文件末尾而不是开头。当您使用"w"
打开时,truncate the file and start writing from position 0:
w或wb
截断为零长度或创建用于写入的文件。
然后你可能想要考虑文件锁定,以防止两个进程同时写入文件。
此外,您的子进程会写出nul终结符:
fwrite("child", 1, 6, fp);
但您的父进程不会:
fwrite("parent", 1, 6, fp);
这可能是也可能不是你的意图,但看起来确实很奇怪。
答案 1 :(得分:1)
你的逻辑是有缺陷的。父进程在等待子进程发出信号之前不会通知子进程。子进程在写入文件并发信号通知父进程之前等待父进程发出信号。
这意味着在父文件中写入文件后,父文件和子文件都会陷入繁忙的循环中,等待另一个人做某事。
此外,虽然我认为这不是代码中的问题,因为调用sigpause(0);
会导致编译器认为全局变量可能已更改并需要重新加载,在其他情况下,您可能会想要将myFlag
声明为volatile int myFlag;
。这会强制编译器在每次引用时从内存中读取或写入其值。
最后,当然,您的程序只会重复写入相同的字节,因为您以"w"
(写入)模式而不是"a"
(追加)模式打开文件。
这是一个使用POSIX标准调用和技术完成您想要的程序,而不是您正在使用旧的已弃用的过时调用:
#include <stdio.h> /* basic I/O routines. */
#include <unistd.h> /* define fork(), etc. */
#include <sys/types.h> /* define pid_t, etc. */
#include <sys/wait.h> /* define wait(), etc. */
#include <signal.h>
#include <stdlib.h>
volatile sig_atomic_t myFlag = 0;
void myHandler(int);
int child_pid;
int main()
{
signal (SIGUSR1, myHandler);
child_pid = fork();
if (child_pid==0) {
for ( ; ; ) {
while(myFlag == 0)
;
{
sigset_t oldmask;
sigset_t usr1;
sigemptyset(&oldmask);
sigemptyset(&usr1);
sigaddset(&usr1, SIGUSR1);
sigprocmask(SIG_BLOCK, &usr1, &oldmask);
myFlag = 0;
sigprocmask(SIG_SETMASK, &oldmask, NULL);
}
FILE *fp=fopen("test","a");
fwrite("child\n",1,6,fp);
fclose(fp);
kill(getppid(),SIGUSR1);
}
}
if (child_pid>0){
FILE *fp;
fp=fopen("test","a");
fwrite("parent\n",1,7,fp);
fclose(fp);
for ( ; ; ) {
kill(child_pid, SIGUSR1);
//kill ()-child_pid ;
while(myFlag == 0)
;
{
sigset_t oldmask;
sigset_t usr1;
sigemptyset(&oldmask);
sigemptyset(&usr1);
sigaddset(&usr1, SIGUSR1);
sigprocmask(SIG_BLOCK, &usr1, &oldmask);
myFlag = 0;
sigprocmask(SIG_SETMASK, &oldmask, NULL);
}
fp=fopen("test","a");
fwrite("parent\n",1,7,fp);
fclose(fp);
}
}
exit(0);
}
void myHandler(int sigNo) {
myFlag = 1;
//signal (SIGUSR1, myHandler);
}