【问题标题】:Linux C comunication beetween processes using signals and pipes使用信号和管道在进程之间进行 Linux C 通信
【发布时间】:2013-06-15 20:57:26
【问题描述】:

我有一个用 C 语言编写的程序。它必须创建 3 个一直工作的进程。这 3 个进程接收信号(停止、暂停、恢复),当它接收到其中一个信号时,它会向其余进程发送其他信号,然后将他收到的信号写入管道(它必须是管道)。其他人接收该信号并读取管道并执行管道中所说的操作。 我有类似的东西要在信号处理程序中写一个管道:

void rcvkillsig(int sig){
  if(sig==SIGINT){
    int op;
    op = 1;
    close(pfd1[0]);
    close(pfd3[0]);
    write(pfd1[1], &op, 8);
    write(pfd3[1], &op, 8);
    close(pfd1[1]);
    close(pfd3[1]);
    kill(sndpid, SIGCONT);
    kill(rcvpid, SIGCONT);
    printf("End chk\n");
    kill(chkpid, SIGKILL);
  }
}

还有类似的读取管道:

void rcvinfsig(int sig){        
  if(sig==SIGCONT){
    cflag=0;
    int op;
    close(pfd2[1]);
    read(pfd2[0], &op, 8);
    close(pfd2[0]);
    if(op==1){
        kill(chkpid, SIGKILL);
        printf("End chk\n");
    }
    else if(op==2){
        printf("Pause chk!\n");
        cpaused=1;
    }
    else if(op==3){
        printf("Resume chk!\n");
        cpaused=0;
    }
  }
}

当然,每个进程都有类似的代码,以及接收到的信号。

我在这个程序中为每个进程使用 pfd1[2]、pfd2[2]、pfd3[2],并在 main 函数中通过 pipe(...) 为它们创建管道。

我的问题是,当进程接收到第一个信号(例如暂停)时,他写入管道,但是当它接收到第二个信号(例如恢复)时,它不写入管道,并且只恢复自身。

请帮我在星期一需要那个程序。其余的代码都可以工作,而我的沟通方式不止这些。

【问题讨论】:

    标签: c linux signals communication pipe


    【解决方案1】:

    根据发布的功能,我认为您的代码存在两个主要问题。

    1.在每次调用信号处理程序时关闭文件描述符。

    这不是一个好主意 - 每次读取或写入后关闭文件描述符。 单向管道不能以这种方式工作。创建描述符对后 您应该在一个进程中关闭第一个描述符,然后在另一个进程中关闭第二个描述符。 这将创建一个从第一个进程到第二个进程的管道 (man pipe)。在手册页的示例中,他们关闭了描述符 写完之后,因为他们不再需要它了。

    2。好像你只有 3 对文件描述符。

    通过单向管道连接3个进程(如下图),需要6对描述符:

                      fd 5,6                  
      +------------+           +------------+ 
      |            |<----------|            |   
      | process #0 |           | process #1 | 
      |            |---------->|            |   
      +------------+           +------------+     
           |   ^      fd 7,8       |   ^           
           |   |                   |   |          
    fd 1,2 |   | fd 3,4    fd 9,10 |   | fd 11,12
           |   |                   |   |             
           v   |                   |   |            
      +------------+               |   |            
      |            |<--------------+   | 
      | process #2 |                   | 
      |            |-------------------+ 
      +------------+                            
    

    示例。

    这是一个代码示例,它做同样的事情。它与好的例子相去甚远(糟糕的信号处理,信号处理程序中的printf),但我希望它会有所帮助。

    int g_pfd[3][2][2];  // pairs of file desriptors.
    
    volatile sig_atomic_t g_ignore_sighup = 0; // flag for ignoring SIGHUP
    
    void ( * g_handlers[3] ) ( int );  // array of signal handlers
    
    void sig_handler ( int signo, int id )
    {
        if ( signo == SIGHUP )
        {
            if ( g_ignore_sighup )
            {
                g_ignore_sighup = 0;
                return;
            }
    
            printf ( "SIGHUP recvd, pid = %d\n", getpid () );
    
            int rd1 = ( id );
            int rd2 = ( id == 0 ? 2 : id - 1 );
    
            // choose, which process sent SIGHUP.
    
            fd_set rfds;
            FD_ZERO ( &rfds );
            FD_SET ( g_pfd[rd1][1][0], &rfds );
            FD_SET ( g_pfd[rd2][0][0], &rfds );
    
            int rv = select ( FD_SETSIZE, &rfds, NULL, NULL, NULL );
    
            if ( rv == -1 )
            {
                perror ( "select" );
                return;
            }
            else if ( rv == 0 )
            {
                return;
            }
    
            int fd = -1;
            if ( FD_ISSET ( g_pfd[rd1][1][0], &rfds ) ) fd = g_pfd[rd1][1][0];
            if ( FD_ISSET ( g_pfd[rd2][0][0], &rfds ) ) fd = g_pfd[rd2][0][0];
    
            int i;
    
            if ( read ( fd, &i, sizeof ( int ) ) == -1 )
            {
                perror ( "read" );
            }
    
            printf ( "recvd data through pipe = %d\n", i );
            return;
        }
    
        if ( signo == SIGINT )
        {
            int wr1 = ( id );
            int wr2 = ( id == 0 ? 2 : id - 1 );
    
            printf ( "SIGINT recvd, pid = %d\n", getpid () );
            printf ( "write: %d to %d\n", getpid (), g_pfd[wr1][0][1] );
            printf ( "write: %d to %d\n", getpid (), g_pfd[wr2][1][1] );
    
            int pid = getpid ();
            if ( write ( g_pfd[wr1][0][1], &pid, sizeof ( int ) ) == -1 ||
                 write ( g_pfd[wr2][1][1], &pid, sizeof ( int ) ) == -1 )
            {
                perror ( "write" );
            }
    
            g_ignore_sighup = 1;  // flag for ignorig own signal
    
            // send SIGHUP to parent and all its children.
    
            if ( kill ( 0, SIGHUP ) == -1 )  
            {
                perror ( "kill" );
            }
    
            return;
        }
    }
    
    void sig_handler_0 ( int signo ) { sig_handler ( signo, 0 ); }
    void sig_handler_1 ( int signo ) { sig_handler ( signo, 1 ); }
    void sig_handler_2 ( int signo ) { sig_handler ( signo, 2 ); }
    
    int create_process ( int *pid, int id )
    {
        *pid = fork ();
    
        if ( *pid == -1 )
        {
            perror ( "fork" );
            return 1;
        }
    
        if ( *pid != 0 )  // parent
        {
            return 0;
        }
    
        // close appropriate descriptors
    
        int i1 = ( id );
        int i2 = ( id == 0 ? 2 : id - 1 );
    
        close ( g_pfd[i1][0][0] );
        close ( g_pfd[i2][0][1] );
        close ( g_pfd[i1][1][1] );
        close ( g_pfd[i2][1][0] );
    
        if ( signal ( SIGINT, g_handlers[id] ) == SIG_ERR ||
             signal ( SIGHUP, g_handlers[id] ) == SIG_ERR )
        {
            perror ( "signal" );
            return 1;
        }
    
        while ( 1 ) sleep ( 1 );
        exit  ( 0 );
    }
    
    int main ( int argc, char *argv [] )
    {
        // fill array of signal handlers.
    
        g_handlers[0] = sig_handler_0;
        g_handlers[1] = sig_handler_1;
        g_handlers[2] = sig_handler_2;
    
        if ( signal ( SIGHUP, SIG_IGN ) == SIG_ERR ) 
        {
            perror ( "signal" );
            return 1;    
        }
    
        int pid [3];
        int i, j;
    
        // create pairs of descriptors
    
        for ( i = 0; i < 3; i++ )
        {
            for ( j = 0; j < 2; j++ )
            {
                if ( pipe ( g_pfd[i][j] ) == -1 )
                {
                    perror ( "pipe" );
                    return 1;
                }
            }
        }
    
        if ( create_process ( &pid[0], 0 ) != 0 ||
             create_process ( &pid[1], 1 ) != 0 ||
             create_process ( &pid[2], 2 ) != 0 )
        {
            return 1;
        }
    
        sleep ( 1 );
    
        kill ( pid[0], SIGINT ); sleep ( 3 );
        kill ( pid[1], SIGINT ); sleep ( 3 );
        kill ( pid[2], SIGINT );
        wait ( NULL );
    
        for ( i = 0; i < 3; i++ )
        {
            for ( j = 0; j < 2; j++ )
            {
                close ( g_pfd[i][j][0] );
                close ( g_pfd[i][j][1] );
            }
        }
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多