使用fork()不正确?

时间:2016-05-04 01:15:02

标签: c linux fork

我正在尝试使用fork()来实现消息队列。这就是我所拥有的。

#define DATA_SIZE 256
#define BUFF_SIZE 4096

int main(void) {
    // seed the random number generator
    srand(time(NULL));

    // Parent and Ground Truth Buffers
    char ground_truth[BUFF_SIZE]    = {0};  // used to verify
    char producer_buffer[BUFF_SIZE] = {0};  // used by the parent
    int i = 0;  
    int msqid = 0;
    int rc;
    pid_t msq_pid;

    for (i = 0; i < BUFF_SIZE; ++i) {
        producer_buffer[i] = ground_truth[i] = rand() % 256;
    }

    const key_t s_msq_key = 1337;  // used to create message queue ipc
    const char *const p_msq_key = "/OS_MSG";

    msqid = msgget(s_msq_key, IPC_CREAT | 0660);

    msq_pid = fork();

    if(msq_pid == -1){
       perror("error forking");
       exit(1);
    }

    if(msq_pid > 0){
        rc = msgsnd(msqid, (void*)p_msq_key, sizeof(producer_buffer), 0);
        printf("MESSAGE SENT\n");
        if(rc < 0){
            perror("message send failed");
            exit(1);
        }
        return 1;
    } else {
        if(memcmp(producer_buffer, ground_truth, DATA_SIZE) == 0){
            printf("MESSAGE REC");
            return 1;
        }
        exit(1);
    }

return 0;
}

我添加了我的实际问题。希望这不是太多。这是家庭作业,但我不想只是获得代码的帮助。再一次,我得到的唯一结果是MESSAGE REC而非MESSAGE SENT后跟MESSAGE REC

编辑:

好的,我添加了msq_pid == -1的错误检查。我还注意到,当我重新启动虚拟机时,我能够同时获得MESSAGE SENTMESSAGE REC。在多次运行该程序后,我开始只接收MESSAGE REC。有人可以解释一下吗?

2 个答案:

答案 0 :(得分:2)

根据fork()手册页,您的问题似乎是您让孩子和父母倒置了。 fork()向子进程返回0,返回&gt; 0到父级,并在出错时返回-1。所以在你的代码中你应该有:

if(msg_pqid == 0) { 
     /* The child sends the message */ 
} else { 
    /* Parent receives the message */ 
}

我更喜欢使用这样的开关:

switch ((msg_pqid = fork())) {
case -1: 
    /* Error */
case 0:
    /* Child sends message */
default:
    /* Parent receives message */
}

答案 1 :(得分:0)

正在错误地使用了几个系统调用。

正在忽略来自多个系统调用的返回状态

以下代码:

  1. 干净地编译
  2. 执行所需的操作
  3. 处理所有错误情况
  4. 现在,代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    #include <time.h>    //time()
    
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    #include <unistd.h>  //fork()
    
    #include <string.h>  //memcmp()
    
    
    #define MAX_MSG_LEN (10)
    #define ACT_MSG_LEN (8)
    
    // Parent and Ground Truth Buffers
    struct msgbuf
    {
        long mtype;       /* message type, must be > 0 */
        char mtext[ MAX_MSG_LEN ];    /* message data */
    };
    
    struct msgbuf ground_truth;  // used to verify
    struct msgbuf producer_buffer = {1,"message"}; // used by the parent
    
    int main(void)
    {
        // seed the random number generator
        srand((unsigned)time(NULL));
    
    
    
        //int i = 0;
        int msqid = 0;
        int rc;
        pid_t msq_pid;
        ssize_t rcvStatus;
    
        const key_t s_msq_key = 1337;  // used to create message queue ipc
        //const char *const p_msq_key = "/OS_MSG";
    
        msqid = msgget(s_msq_key, IPC_CREAT | 0660);
        if( -1 == msqid )
        {// then msgget failed
            perror( "msgget failed");
            exit( EXIT_FAILURE );
        }
    
        // implied else, msgget successful
    
        msq_pid = fork();
    
        while(1)
        {
            switch( msq_pid )
            {
                case -1:
                    perror("error forking");
                    exit( EXIT_FAILURE );
                    break;
    
                default:  // parent process
                    rc = msgsnd(msqid, &producer_buffer, sizeof producer_buffer, 0);
                    printf("MESSAGE SENT: %s\n", producer_buffer.mtext);
                    if(rc < 0)
                    {
                        perror("message send failed");
                        exit( EXIT_FAILURE );
                    }
                    break;
    
                case 0:   // child process
                    rcvStatus = msgrcv( msqid, &ground_truth, sizeof( ground_truth ), 0, 0);
                    if( -1 == rcvStatus )
                    { // then msgrcv failed
                        perror( "msgrcv failed" );
                        exit( EXIT_FAILURE );
                    }
    
                    // implied else, msgrcv successful
    
                    if(memcmp(producer_buffer.mtext, ground_truth.mtext, ACT_MSG_LEN) == 0)
                    {
                        printf("MESSAGE REC %s\n", ground_truth.mtext);
                    }
    
                    else
                    {
                        printf( "msg Sent: '%s' does not match msg Recv: '%s'\n", producer_buffer.mtext, ground_truth.mtext);
                    }
                    break;
            } // end switch
        } // end while forever
    } // end function: main