簡體   English   中英

使用信號和管道的進程之間的Linux C通信

[英]Linux C comunication beetween processes using signals and pipes

我有一個用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(...)為它們創建管道。

我的問題是,當進程接收到第一個信號(例如暫停)時,他將其寫入管道,但是當它接收到第二個信號(例如,resume)時,則不寫入管道,而僅恢復自身。

請幫助我星期一需要該程序。 其余代碼工作正常,我沒有那種交流。

基於發布的功能,我認為您的代碼中存在兩個主要問題。

1.在每次信號處理程序調用時關閉文件描述符。

這不是一個好主意-每次讀取或寫入后都關閉文件描述符。 單向管道不能以這種方式工作。 創建描述符對之后,您應該在一個進程中關閉第一個描述符,然后在另一個進程中關閉第二個描述符。 這將創建一個從第一個進程到第二個進程的管道( 手動管道 )。 在手冊頁中的示例中,它們在寫完后立即關閉描述符,因為不再需要它。

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM