开发者

UNIX IPC C program only parent process can write to file, child not working

I need to use Signal to write UNIX Interprocess communication program in C. I want a parent process and child process to write to a same file. The result only show parent written text. I can use either BSD or System V. Please help

#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 sigN开发者_C百科o) {
    myFlag = 1;
    //signal (SIGUSR1, myHandler);
}


You should start by opening the file in append mode rather than write mode:

fp = fopen("test", "a");

That will position the write position of fp at the end of file rather than the beginning. When you open with "w", you truncate the file and start writing from position 0:

w or wb
Truncate to zero length or create file for writing.

Then you might want to think about file locking to keep the two processes from writing to the file at the same time.

Also, your child process writes out the nul terminator:

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

but your parent process doesn't:

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

That may or may not be your intention but it does look odd.


Your logic is flawed. The parent process does not signal the child process before it waits for the child process to signal it. The child process waits for the parent process to signal it before writing the file and signaling the parent process.

This means after you write the file in the parent both the parent and child are stuck in busy loops waiting for the other one to do something.

Also, while I don't think this is a problem in your code since the call to sigpause(0); should cause the compiler to believe that global variables may have changed and need to be reloaded, in other situations you might want to declare myFlag as volatile int myFlag;. This forces the compiler to read or write its value from memory every time you reference it.

Lastly, of course, your programs will simply re-write over the same bytes repeatedly because you open the files in "w" (write) mode instead of "a" (append) mode.

Here's a program that accomplishes what you want using POSIX standard calls and techniques instead of the old deprecated obsolete calls you were using:

#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);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜