Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
UNIX IPC C程序只有父进程可以写入文件,子进程不工作_Unix_Ipc_Signals - Fatal编程技术网

UNIX IPC C程序只有父进程可以写入文件,子进程不工作

UNIX IPC C程序只有父进程可以写入文件,子进程不工作,unix,ipc,signals,Unix,Ipc,Signals,我需要使用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.

我需要使用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);
}
#包括/*基本I/O例程*/
#包括/*定义fork()等*/
#包括/*定义pid等*/
#包括/*定义等待()等*/
#包括
int myFlag=0;
void myHandler(int);
int-child_-pid;
int main()
{
//oldmask=sigblock(sigmask(SIGUSR1));
sighold(SIGUSR1);
sighold(SIGINT);
/*临界区*/
信号(SIGUSR1,myHandler);
sigrelse(SIGUSR1);
sigrelse(SIGINT);
child_pid=fork();
如果(子项pid==0){
对于(;;){
while(myFlag==0)
信号暂停(0);
sigblock(sigmask(SIGUSR1));
myFlag=0;
文件*fp=fopen(“测试”,“w”);
fwrite(“儿童”,1,6,fp);
fclose(fp);
kill(getppid(),SIGUSR1);
}       
}  
如果(子项pid>0){
文件*fp;
fp=fopen(“试验”,“w”);
fwrite(“父”,1,6,fp);
fclose(fp);
对于(;;){
while(myFlag==0)
信号暂停(0);
sigblock(sigmask(SIGUSR1));
myFlag=0;
fp=fopen(“试验”,“w”);
fwrite(“父”,1,6,fp);
fclose(fp);
}           
kill(child_pid,SIGUSR1);
//kill()-child_-pid;
}   
出口(0);
}
void myHandler(int sigNo){
myFlag=1;
//信号(SIGUSR1,myHandler);
}

您应该以追加模式而不是写入模式打开文件:

fp = fopen("test", "a");
这将把
fp
的写入位置定位在文件的末尾而不是开头。当您使用
“w”
打开时,您:

w或wb
截断为零长度或创建用于写入的文件

然后,您可能需要考虑文件锁定,以防止两个进程同时写入文件

此外,您的子进程会写出nul终止符:

fwrite("child", 1, 6, fp);
但您的父进程没有:

fwrite("parent", 1, 6, fp);

这可能是你的意图,也可能不是,但看起来确实很奇怪。

你的逻辑有缺陷。父进程在等待子进程向其发送信号之前不会向子进程发送信号。子进程等待父进程向其发送信号,然后再写入文件并向父进程发送信号

这意味着在父级中写入文件后,父级和子级都陷入繁忙的循环中,等待另一个执行某些操作

另外,虽然我不认为这是代码中的问题,因为调用
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);
}
#包括/*基本I/O例程*/
#包括/*定义fork()等*/
#包括/*定义pid等*/
#包括/*定义等待()等*/
#包括
#包括
易失性sig_atomic_t myFlag=0;
void myHandler(int);
int-child_-pid;
int main()
{
信号(SIGUSR1,myHandler);
child_pid=fork();
如果(子项pid==0){
对于(;;){
while(myFlag==0)
;
{
sigset\u t oldsmask;
sigset_t usr1;
SIGEPTYSET(&oldmask);
sigemptyset(&usr1);
sigaddset(&usr1,SIGUSR1);
sigprocmask(SIG_块、usr1和oldmask);
myFlag=0;
sigprocmask(SIG_设置掩码和旧掩码,NULL);
}
文件*fp=fopen(“测试”,“a”);
fwrite(“child\n”,1,6,fp);
fclose(fp);
kill(getppid(),SIGUSR1);
}
}
如果(子项pid>0){
文件*fp;
fp=fopen(“测试”、“a”);
fwrite(“父项”,1,7,fp);
fclose(fp);
对于(;;){
kill(child_pid,SIGUSR1);
//kill()-child_-pid;
while(myFlag==0)
;
{
sigset\u t oldsmask;
sigset_t usr1;
SIGEPTYSET(&oldmask);
sigemptyset(&usr1);
sigaddset(&usr1,SIGUSR1);
sigprocmask(SIG_块、usr1和oldmask);
myFlag=0;
sigprocmask(SIG_设置掩码和旧掩码,NULL);
}
fp=fopen(“测试”、“a”);
fwrite(“父项”,1,7,fp);
fclose(fp);
}
}
出口(0);
}
void myHandler(int sigNo){
myFlag=1;
//信号(SIGUSR1,myHandler);
}

尽量不要将代码缩进10-12个空格-这会使阅读变得非常困难,页面的右侧也会消失。最多8个空格;我使用4个空格,尽管有些人使用3个空格。您会发现一些书籍只使用了几个空格,但它们受到打印布局的限制……而且,
sigrelse()
是POSIX中过时的函数。新代码(如您的)不应使用它。像你这样使用它们也有点毫无意义,IMNSHO。麻烦那些需要上床睡觉的孩子们……我要说的大部分要点都是你说的。将打开、写入和关闭文件的代码分解成一个函数是明智的。可以传递文件名;应该传递字符串;它可以使用'
fprintf(fp,“%s\n”,str)
在字符串后面写一个换行符,这将提高可读性