在IPC设置中初始化条件变量和/或互斥对象时出错

Trouble initializing condition variable and/or mutex -- in an IPC setup

本文关键字:对象 出错 设置 IPC 初始化 变量 条件      更新时间:2023-10-16

我有以下代码,它初始化一个包含1个互斥和1个条件变量的共享内存,然后分叉一个进程,父进程通过管道将一些字符传递给子进程,并向子进程发出读取信号。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <pthread.h>

#ifndef _POSIX_THREAD_PROCESS_SHARED
#error This system does not support process shared mutex
#endif
pthread_cond_t *cvptr;    //Condition Variable Pointer
pthread_condattr_t cattr; //Condition Variable Attribute
pthread_mutex_t    *mptr; //Mutex Pointer
pthread_mutexattr_t matr; //Mutex Attribute
int   shared_mem_id;      //shared memory Id
int   *mp_shared_mem_ptr; //shared memory ptr -- pointing to mutex
int   *cv_shared_mem_ptr; //shared memory ptr -- pointing to condition variable
/* Read characters from the pipe and echo them to stdout. */
void read_from_pipe (int file)
{
    printf("read_from_pipe()n");
    FILE *stream;
    int c;
    stream = fdopen (file, "r");
    // Lock mutex and then wait for signal to relase mutex
    printf("child mutex lock n");
    pthread_mutex_lock( mptr );
    printf("child mutex lockedn");
    printf("child waitn");
    pthread_cond_wait( cvptr, mptr );
    printf("child condition woke upn");
    while ((c = fgetc (stream)) != EOF) 
        putchar (c);
    fclose (stream);
    printf("child mutex unlockn");
    pthread_mutex_unlock( mptr );
}
/* Write some random text to the pipe. */
void write_to_pipe (int file)
{
    printf("write_to_pipe()n");
    FILE *stream;
    stream = fdopen (file, "w");
    fprintf (stream, "hello, world!n");
    fprintf (stream, "goodbye, world!n");
    fclose (stream);
    pthread_cond_signal( cvptr );
}
int main (void)
{
    int  rtn;
    size_t shm_size;
    /* initialize shared memory segment */
    shm_size = 1*sizeof(pthread_mutex_t) + 1*sizeof(pthread_cond_t);
    if ((shared_mem_id = shmget(IPC_PRIVATE, shm_size, 0660)) < 0)
    {
        perror("shmget"), exit(1) ;
    }
    if ((mp_shared_mem_ptr = (int *)shmat(shared_mem_id, (void *)0, 0)) == NULL)
    {
        perror("shmat"), exit(1);
    }
    //Offset to find the location of the condition variable in the shared memory
    unsigned char* byte_ptr = reinterpret_cast<unsigned char*>(mp_shared_mem_ptr);
    byte_ptr += 1*sizeof(pthread_mutex_t);
    mptr = (pthread_mutex_t *)mp_shared_mem_ptr;
    cvptr = (pthread_cond_t *)byte_ptr;
    // Setup Mutex
    if (rtn = pthread_mutexattr_init(&matr)) 
    {
        fprintf(stderr,"pthreas_mutexattr_init: %s",strerror(rtn)),exit(1);
    }
    if (rtn = pthread_mutexattr_setpshared(&matr,PTHREAD_PROCESS_SHARED))
    {
        fprintf(stderr,"pthread_mutexattr_setpshared %s",strerror(rtn)),exit(1);
    }
    if (rtn = pthread_mutex_init(mptr, &matr))
    {
        fprintf(stderr,"pthread_mutex_init %s",strerror(rtn)), exit(1);
    }
    //Setup Condition Variable
    if(rtn = pthread_condattr_init(&cattr))
    {
        fprintf(stderr,"pthread_condattr_init: %s",strerror(rtn)),exit(1);
    }
    if(pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED))
    {
        fprintf(stderr,"pthread_condattr_setpshared %s",strerror(rtn)),exit(1);
    }
    if(pthread_cond_init(cvptr, &cattr))
    {
        fprintf(stderr,"pthread_cond_init %s",strerror(rtn)),exit(1);
    }
    pid_t pid;
    int mypipe[2];
    /* Create the pipe. */
    if (pipe (mypipe))
    {
        fprintf (stderr, "Pipe failed.n");
        return EXIT_FAILURE;
    }
    /* Create the child process. */
    pid = fork ();
    if (pid == (pid_t) 0)
    {
        printf ("Child Forked!.n");
        /* This is the child process.
        Close other end first. */
        close (mypipe[1]);
        read_from_pipe (mypipe[0]);
        return EXIT_SUCCESS;
    }
    else if (pid < (pid_t) 0)
    {
        /* The fork failed. */
        fprintf (stderr, "Fork failed.n");
        return EXIT_FAILURE;
    }
    else
    {
        printf ("Parent Forked!.n");
        /* This is the parent process.
        Close other end first. */
        close (mypipe[0]);
        write_to_pipe (mypipe[1]);
        return EXIT_SUCCESS;
    } 
}

我想我在初始化变量时做错了什么,代码没有核心转储,但不知何故只打印:

Parent Forked!.
write_to_pipe()

有什么想法吗?

write_to_pipe可能在read_from_pipe到达pthread_cond_wait之前发出条件变量的信号。条件变量不会对信号进行任何缓冲或计数,因此它只会丢失。