UNIX IPC C программа только родительский процесс может записывать в файл, дочерний процесс не работает - PullRequest
1 голос
/ 07 мая 2011

Мне нужно использовать Signal для написания межпроцессной коммуникационной программы UNIX на C. Я хочу, чтобы родительский и дочерний процессы записывали в один и тот же файл. В результате показывается только родительский письменный текст. Я могу использовать либо 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);
}

Ответы [ 2 ]

1 голос
/ 07 мая 2011

Ваша логика ошибочна.Родительский процесс не сигнализирует дочерний процесс, пока он не ждет, пока дочерний процесс не сигнализирует о нем.Дочерний процесс ждет, пока родительский процесс не сигнализирует об этом, прежде чем записывать файл и сигнализировать о родительском процессе.

Это означает, что после записи файла в родительский процесс родительский и дочерний процессы застревают в занятых циклах, ожидаядругой, чтобы сделать что-то.

Кроме того, хотя я не думаю, что это проблема в вашем коде, так как вызов 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);
}
1 голос
/ 07 мая 2011

Вы должны начать с открытия файла в режиме добавления, а не в режиме записи:

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

Это позиционирует позицию записи fp в конце файла, а не в начале. Когда вы открываете "w", вы усекаете файл и начинаете запись с позиции 0 :

ш или ш
Обрезать до нулевой длины или создать файл для записи.

Тогда вы можете подумать о блокировке файла, чтобы не допустить одновременной записи в файл двумя процессами.

Кроме того, ваш дочерний процесс записывает нулевой терминатор:

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

но ваш родительский процесс не:

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

Это может или не может быть вашим намерением, но это выглядит странно.

...