C 使用命名信号量的死锁

C 使用命名信号量的死锁,c,deadlock,semaphore,shared-memory,posix-api,C,Deadlock,Semaphore,Shared Memory,Posix Api,我正在尝试使用共享内存和命名信号量来同步对它的访问 我的程序有3个进程——父进程1和两个子进程,它们都必须使用相同的进程 共享内存。为了在它们之间同步,我使用了名为sempahore的。 它们共享的资源是一个3整数数组,当数组[0]-退出标志位置时,子进程在操作前读取该数组,以确定父进程是否要退出。 数组[1]、数组[2]-用于与父进程通信,每个进程在其自己的数组单元中放置一条消息,父进程读取该消息,并在respone中放置一条确认消息 我正在尝试获取我的代码的基本工作流程-生成所有必要的资源,

我正在尝试使用共享内存和命名信号量来同步对它的访问

我的程序有3个进程——父进程1和两个子进程,它们都必须使用相同的进程 共享内存。为了在它们之间同步,我使用了名为sempahore的。 它们共享的资源是一个3整数数组,当数组[0]-退出标志位置时,子进程在操作前读取该数组,以确定父进程是否要退出。 数组[1]、数组[2]-用于与父进程通信,每个进程在其自己的数组单元中放置一条消息,父进程读取该消息,并在respone中放置一条确认消息

我正在尝试获取我的代码的基本工作流程-生成所有必要的资源,让父级睡眠3秒钟,然后启动exit_过程

我的问题是,当进入exit_过程时,主进程将永远阻塞sem_wait()操作-显然是死锁。 我正试图找出这个问题,但似乎无法指出它。 我是处理同步的新手-在这段代码之前,我只同步线程

更新: 我已经使用POSIX内存映射进行了切换,现在我遇到了相同的死锁问题。process_api.h中的相关方法无法获得锁,它们只是永远阻塞。我不知道我做错了什么。 能请一些人帮忙吗

我的代码:

主文件:

int *shmem_p;       //!< Shared variable to be used across different proccesses
int shmem_fd;       //!< Shared memory id
sem_t *sem_p;       //!< Sempahore for syncronizing access to shared memory

volatile sig_atomic_t done;         //!< An atomic flag to signal this process threads they are done
volatile sig_atomic_t signal_rcvd;  //!< Indication to exit procedure if a signal caused termination

/**
 * @brief Exit procedure to be called when program is done
 */
static void exit_procedure()
{
    block_all_signals();            /* Block all signals - we're already existing */

    if(signal_rcvd == SIGTERM) {    /* SIGTERM is manually raised by us when a thread terminates, thus not handled in signal handler */
        write(STDERR_FILENO, "Error occured - thread terminated\n", 33);
    }

    if( !signal_rcvd ) {            /* We got here normally, or by thread termination - set done flag */
        done = true;
    }

    /* Free all relevant resources */
    sem_unlink("/shmemory");
    sem_close(sem_p);

    munmap(shmem_p, TOTAL_PROC_NUM*sizeof(int));
    shm_unlink("/shmemory");

    sem_p = NULL;
    shmem_p = NULL;
}

static void signal_handler(int sig_num) {
    switch(sig_num) {
    case SIGCHLD:
        write(STDERR_FILENO, "Error occured - Child process terminated\n", 43);
        break;

    case SIGALRM:
        write(STDOUT_FILENO, "Successfully finished sim\n", 28);
        break;

    default:
        fprintf(stderr, "Error - Signal %s has been raised", strsignal(sig_num));
        fflush(stderr);
        break;
    }

    done = true;
    signal_rcvd = true;
}

static status_t init_procedure()
{
    done = false;
    signal_rcvd = false;
    size_t size = TOTAL_PROC_NUM*sizeof(int);

    /* Initialize shared memory to be used as an exit flag to be used by all processes */

    shmem_fd = shm_open("/shmemory", O_CREAT | O_TRUNC | O_RDWR, 0644);
    if(shmem_fd < 0) {
        error_and_exit("shm_open() failed, err = ", errno);
    }

    if(ftruncate(shmem_fd, size)) {
        shm_unlink("/shmemory");
        error_and_exit("ftruncate() failed, err = ", errno);
    }

    shmem_p = (int *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
    if(shmem_p == MAP_FAILED) {
        shm_unlink("/shmemory");
        error_and_exit("mmap() failed, err = ", errno);
    }

    close(shmem_fd);    /* No longer needed */
    memset(shmem_p, 0, size);

    /* Initialize a named sempahore for the procceses shared memory */
    sem_p = sem_open("/shsemaphore", O_CREAT | O_RDWR, 0644, 1);
    if(SEM_FAILED == sem_p) {
        error("sem_open() failed, err = ", errno);
        munmap(shmem_p, size);
        shm_unlink("/shmemory");
    }

    /* Initialize memory access invokers processes */
    if(processes_init() != SUCCESS) {
        error("init_processes() failed\n", ERR);
        munmap(shmem_p, size);
        shm_unlink("/shmemory");
        sem_close(sem_p);
        return FAILURE;
    }

    /* Handle Signals - Ignore SIGINT, SIGQUIT, handle SIGCHLD & SIGALRM */

    struct sigaction sig_handler;
    sig_handler.sa_flags = 0;

    if(sigfillset(&sig_handler.sa_mask)) {  /* Mask all other signals inside the handler */
        error("sigemptyset() failed, err = ", errno);
        exit_procedure();
        return FAILURE;
    }

    sig_handler.sa_handler = signal_handler;
    if(sigaction(SIGCHLD, &sig_handler, NULL) || sigaction(SIGALRM, &sig_handler, NULL)) {  /* Set the signal handler for SIGCHLD & SIGALRM */
        error("sigaction() failed, err = ", errno);
        exit_procedure();
        return FAILURE;
    }

    sig_handler.sa_handler = SIG_IGN;
    if(sigaction(SIGINT, &sig_handler, NULL) || sigaction(SIGQUIT, &sig_handler, NULL)) {   /* Ignore ctrl+c and ctrl+z */
        error("sigaction() failed, err = ", errno);
        exit_procedure();
        return FAILURE;
    }

    return SUCCESS;
}

int main(int argc, char *argv[])
{
    if(argc != 1) {
        fprintf(stderr, "usage: %s (no arguments allowed)\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if(SUCCESS != init_procedure()) {
        error_and_exit("init_procedure() failed\n", ERR);
    }

    sleep(5);
    exit_procedure();

    return EXIT_SUCCESS;
}
#define WR_RATE (0.8)               //!< Writing probabilty when invoking memory access
#define WR_RATE_INT (WR_RATE*10)    //!< WR_RATE as an int value between 1 and 10
#define INTER_MEM_ACCS_T (100000)   //!< Waiting time between memory accesses

static pid_t child_pids[CHILD_PROC_NUM];

int process_cnt;                    //!< Determines the index of the process, for child processes
extern sem_t *sem_p;

static bool is_ack_received(int *mem_p, off_t size)
{
    bool ack;

    /*********************************************************/
    /**                 Critical Section start              **/
    if((sem_wait(sem_p) != 0) && (errno != EINTR)) {
        munmap(mem_p, size);
        shm_unlink("/shmemory");
        error_and_Exit("sem_wait() failed, err = ", errno);
    }

    ack = (mem_p[process_cnt] == MSG_ACK);

    if(ack) {// TODO - Remove
        fprintf(stdout, "Process %d received ACK\n", process_cnt);
        fflush(stdout);
    }

    if((sem_post(sem_p) != 0) && (errno != EINTR)) {
        munmap(mem_p, size);
        shm_unlink("/shmemory");
        error_and_Exit("sem_post() failed, err = ", errno);
    }
    /**                 Critical Section end                **/
    /*********************************************************/

    return ack;
}

static void invoke_memory_access(int *mem_p, off_t size)
{
    msg_e send_msg = MSG_READ;
    if(rand_range(1, 10) <= WR_RATE_INT) {  /* Write Memory */
        send_msg = MSG_WRITE;
    }

    /*********************************************************/
    /**                 Critical Section start              **/
    if((sem_wait(sem_p) != 0) && (errno != EINTR)) {  
        munmap(mem_p, size);
        shm_unlink("/shmemory");
        error_and_Exit("sem_wait() failed, err = ", errno);
    }

    mem_p[process_cnt] = send_msg;
    fprintf(stdout, "Process %d sent MSG_%d in mem_address: %p\n", process_cnt, send_msg, &mem_p[process_cnt]); // TODO - Remove
    fflush(stdout);

    if((sem_post(sem_p) != 0) && (errno != EINTR)) {
        munmap(mem_p, size);
        shm_unlink("/shmemory");
        error_and_Exit("sem_post() failed, err = ", errno);
    }
    /**                 Critical Section end                **/
    /*********************************************************/
}

static void main_loop()
{
    int shmem_fd = shm_open("/shmemory", O_RDWR, 0);
    if(shmem_fd < 0) {
        error_and_Exit("shm_open() failed, err = ", errno);
    }

    struct stat mem_stat;
    fstat(shmem_fd, &mem_stat);

    int *child_memory_p = (int *)mmap(NULL, mem_stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
    if(child_memory_p == MAP_FAILED) {
        shm_unlink("/shmemory");
        error_and_Exit("mmap() failed, err = ", errno);
    }

    close(shmem_fd);    /* No longer needed */

    bool first_run = true;
    bool ack = false;
    const struct timespec ns_wait = {.tv_sec = 0, .tv_nsec = INTER_MEM_ACCS_T};

    while(child_memory_p[0] != MSG_EXIT) {
        if( !first_run ) {                  /* Not the first run, check for ack */
            ack = is_ack_received(child_memory_p, mem_stat.st_size);
        }

        nanosleep(&ns_wait, NULL);

        if( !first_run && !ack ) {  /* No ack received for latest call, nothing to be done */
            continue;
        }

        invoke_memory_access(child_memory_p, mem_stat.st_size);

        if(first_run) {             /* First run is over.. */
            first_run = false;
        }
    }

    fprintf(stdout, "PROCCESS %d EXIT!\n", process_cnt); // TODO Remove this
    fflush(stdout);

    munmap(child_memory_p, mem_stat.st_size);
    shm_unlink("/shmemory");

    child_memory_p = NULL;

    _Exit(EXIT_SUCCESS);
}

status_t processes_init()
{
    pid_t pid;
    process_cnt = 1;    /* Will be used for child processes to determine their order creation */
    int i;
    for(i = 0; i < CHILD_PROC_NUM; ++i) {
        pid = fork();

        if(ERR == pid) {
            error("fork() failed, err = ", errno);
            return FAILURE;
        } else if(pid != 0) {           /* Parent process */
            child_pids[i] = pid;
            process_cnt++;
        } else {                        /* Child process */
            block_all_signals();        /* Only main process responsible for indicate exit to its child*/
            main_loop();
        }
    }

    return SUCCESS;
}

void processes_deinit(int **mem_p)
{
    (*mem_p)[0] = MSG_EXIT;
    fprintf(stdout, "EXIT wrriten to address %p\n", *mem_p);

    /* Wait for all child processes to terminate */
    int i;
    write(STDOUT_FILENO, "Waiting for children to exit\n", 29); // TODO Remove this
    for(i = 0; i < CHILD_PROC_NUM; ++i) {
        if((ERR == waitpid(child_pids[i], NULL, 0)) && (ECHILD != errno)) {
            error("waitpid() failed, err = ", errno);
        }
    }

    fprintf(stdout, "PROCCESS DEINIT DONE!\n"); // TODO Remove this
    fflush(stdout);
}
int*shmem\u p;/!<要跨不同进程使用的共享变量
int shmem_fd;/!<共享内存id
sem_t*sem_p;/!
进程处理程序:

int *shmem_p;       //!< Shared variable to be used across different proccesses
int shmem_fd;       //!< Shared memory id
sem_t *sem_p;       //!< Sempahore for syncronizing access to shared memory

volatile sig_atomic_t done;         //!< An atomic flag to signal this process threads they are done
volatile sig_atomic_t signal_rcvd;  //!< Indication to exit procedure if a signal caused termination

/**
 * @brief Exit procedure to be called when program is done
 */
static void exit_procedure()
{
    block_all_signals();            /* Block all signals - we're already existing */

    if(signal_rcvd == SIGTERM) {    /* SIGTERM is manually raised by us when a thread terminates, thus not handled in signal handler */
        write(STDERR_FILENO, "Error occured - thread terminated\n", 33);
    }

    if( !signal_rcvd ) {            /* We got here normally, or by thread termination - set done flag */
        done = true;
    }

    /* Free all relevant resources */
    sem_unlink("/shmemory");
    sem_close(sem_p);

    munmap(shmem_p, TOTAL_PROC_NUM*sizeof(int));
    shm_unlink("/shmemory");

    sem_p = NULL;
    shmem_p = NULL;
}

static void signal_handler(int sig_num) {
    switch(sig_num) {
    case SIGCHLD:
        write(STDERR_FILENO, "Error occured - Child process terminated\n", 43);
        break;

    case SIGALRM:
        write(STDOUT_FILENO, "Successfully finished sim\n", 28);
        break;

    default:
        fprintf(stderr, "Error - Signal %s has been raised", strsignal(sig_num));
        fflush(stderr);
        break;
    }

    done = true;
    signal_rcvd = true;
}

static status_t init_procedure()
{
    done = false;
    signal_rcvd = false;
    size_t size = TOTAL_PROC_NUM*sizeof(int);

    /* Initialize shared memory to be used as an exit flag to be used by all processes */

    shmem_fd = shm_open("/shmemory", O_CREAT | O_TRUNC | O_RDWR, 0644);
    if(shmem_fd < 0) {
        error_and_exit("shm_open() failed, err = ", errno);
    }

    if(ftruncate(shmem_fd, size)) {
        shm_unlink("/shmemory");
        error_and_exit("ftruncate() failed, err = ", errno);
    }

    shmem_p = (int *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
    if(shmem_p == MAP_FAILED) {
        shm_unlink("/shmemory");
        error_and_exit("mmap() failed, err = ", errno);
    }

    close(shmem_fd);    /* No longer needed */
    memset(shmem_p, 0, size);

    /* Initialize a named sempahore for the procceses shared memory */
    sem_p = sem_open("/shsemaphore", O_CREAT | O_RDWR, 0644, 1);
    if(SEM_FAILED == sem_p) {
        error("sem_open() failed, err = ", errno);
        munmap(shmem_p, size);
        shm_unlink("/shmemory");
    }

    /* Initialize memory access invokers processes */
    if(processes_init() != SUCCESS) {
        error("init_processes() failed\n", ERR);
        munmap(shmem_p, size);
        shm_unlink("/shmemory");
        sem_close(sem_p);
        return FAILURE;
    }

    /* Handle Signals - Ignore SIGINT, SIGQUIT, handle SIGCHLD & SIGALRM */

    struct sigaction sig_handler;
    sig_handler.sa_flags = 0;

    if(sigfillset(&sig_handler.sa_mask)) {  /* Mask all other signals inside the handler */
        error("sigemptyset() failed, err = ", errno);
        exit_procedure();
        return FAILURE;
    }

    sig_handler.sa_handler = signal_handler;
    if(sigaction(SIGCHLD, &sig_handler, NULL) || sigaction(SIGALRM, &sig_handler, NULL)) {  /* Set the signal handler for SIGCHLD & SIGALRM */
        error("sigaction() failed, err = ", errno);
        exit_procedure();
        return FAILURE;
    }

    sig_handler.sa_handler = SIG_IGN;
    if(sigaction(SIGINT, &sig_handler, NULL) || sigaction(SIGQUIT, &sig_handler, NULL)) {   /* Ignore ctrl+c and ctrl+z */
        error("sigaction() failed, err = ", errno);
        exit_procedure();
        return FAILURE;
    }

    return SUCCESS;
}

int main(int argc, char *argv[])
{
    if(argc != 1) {
        fprintf(stderr, "usage: %s (no arguments allowed)\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if(SUCCESS != init_procedure()) {
        error_and_exit("init_procedure() failed\n", ERR);
    }

    sleep(5);
    exit_procedure();

    return EXIT_SUCCESS;
}
#define WR_RATE (0.8)               //!< Writing probabilty when invoking memory access
#define WR_RATE_INT (WR_RATE*10)    //!< WR_RATE as an int value between 1 and 10
#define INTER_MEM_ACCS_T (100000)   //!< Waiting time between memory accesses

static pid_t child_pids[CHILD_PROC_NUM];

int process_cnt;                    //!< Determines the index of the process, for child processes
extern sem_t *sem_p;

static bool is_ack_received(int *mem_p, off_t size)
{
    bool ack;

    /*********************************************************/
    /**                 Critical Section start              **/
    if((sem_wait(sem_p) != 0) && (errno != EINTR)) {
        munmap(mem_p, size);
        shm_unlink("/shmemory");
        error_and_Exit("sem_wait() failed, err = ", errno);
    }

    ack = (mem_p[process_cnt] == MSG_ACK);

    if(ack) {// TODO - Remove
        fprintf(stdout, "Process %d received ACK\n", process_cnt);
        fflush(stdout);
    }

    if((sem_post(sem_p) != 0) && (errno != EINTR)) {
        munmap(mem_p, size);
        shm_unlink("/shmemory");
        error_and_Exit("sem_post() failed, err = ", errno);
    }
    /**                 Critical Section end                **/
    /*********************************************************/

    return ack;
}

static void invoke_memory_access(int *mem_p, off_t size)
{
    msg_e send_msg = MSG_READ;
    if(rand_range(1, 10) <= WR_RATE_INT) {  /* Write Memory */
        send_msg = MSG_WRITE;
    }

    /*********************************************************/
    /**                 Critical Section start              **/
    if((sem_wait(sem_p) != 0) && (errno != EINTR)) {  
        munmap(mem_p, size);
        shm_unlink("/shmemory");
        error_and_Exit("sem_wait() failed, err = ", errno);
    }

    mem_p[process_cnt] = send_msg;
    fprintf(stdout, "Process %d sent MSG_%d in mem_address: %p\n", process_cnt, send_msg, &mem_p[process_cnt]); // TODO - Remove
    fflush(stdout);

    if((sem_post(sem_p) != 0) && (errno != EINTR)) {
        munmap(mem_p, size);
        shm_unlink("/shmemory");
        error_and_Exit("sem_post() failed, err = ", errno);
    }
    /**                 Critical Section end                **/
    /*********************************************************/
}

static void main_loop()
{
    int shmem_fd = shm_open("/shmemory", O_RDWR, 0);
    if(shmem_fd < 0) {
        error_and_Exit("shm_open() failed, err = ", errno);
    }

    struct stat mem_stat;
    fstat(shmem_fd, &mem_stat);

    int *child_memory_p = (int *)mmap(NULL, mem_stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
    if(child_memory_p == MAP_FAILED) {
        shm_unlink("/shmemory");
        error_and_Exit("mmap() failed, err = ", errno);
    }

    close(shmem_fd);    /* No longer needed */

    bool first_run = true;
    bool ack = false;
    const struct timespec ns_wait = {.tv_sec = 0, .tv_nsec = INTER_MEM_ACCS_T};

    while(child_memory_p[0] != MSG_EXIT) {
        if( !first_run ) {                  /* Not the first run, check for ack */
            ack = is_ack_received(child_memory_p, mem_stat.st_size);
        }

        nanosleep(&ns_wait, NULL);

        if( !first_run && !ack ) {  /* No ack received for latest call, nothing to be done */
            continue;
        }

        invoke_memory_access(child_memory_p, mem_stat.st_size);

        if(first_run) {             /* First run is over.. */
            first_run = false;
        }
    }

    fprintf(stdout, "PROCCESS %d EXIT!\n", process_cnt); // TODO Remove this
    fflush(stdout);

    munmap(child_memory_p, mem_stat.st_size);
    shm_unlink("/shmemory");

    child_memory_p = NULL;

    _Exit(EXIT_SUCCESS);
}

status_t processes_init()
{
    pid_t pid;
    process_cnt = 1;    /* Will be used for child processes to determine their order creation */
    int i;
    for(i = 0; i < CHILD_PROC_NUM; ++i) {
        pid = fork();

        if(ERR == pid) {
            error("fork() failed, err = ", errno);
            return FAILURE;
        } else if(pid != 0) {           /* Parent process */
            child_pids[i] = pid;
            process_cnt++;
        } else {                        /* Child process */
            block_all_signals();        /* Only main process responsible for indicate exit to its child*/
            main_loop();
        }
    }

    return SUCCESS;
}

void processes_deinit(int **mem_p)
{
    (*mem_p)[0] = MSG_EXIT;
    fprintf(stdout, "EXIT wrriten to address %p\n", *mem_p);

    /* Wait for all child processes to terminate */
    int i;
    write(STDOUT_FILENO, "Waiting for children to exit\n", 29); // TODO Remove this
    for(i = 0; i < CHILD_PROC_NUM; ++i) {
        if((ERR == waitpid(child_pids[i], NULL, 0)) && (ECHILD != errno)) {
            error("waitpid() failed, err = ", errno);
        }
    }

    fprintf(stdout, "PROCCESS DEINIT DONE!\n"); // TODO Remove this
    fflush(stdout);
}
#定义WR#U率(0.8)/!<调用内存访问时的写入概率
#定义WR_RATE_INT(WR_RATE*10)/!