【问题标题】:Handling SIGINT with shared memory and semaphores使用共享内存和信号量处理 SIGINT
【发布时间】:2020-04-29 05:11:46
【问题描述】:

我尝试编写一个共享内存和信号量程序,该程序一直运行到按下 Ctrl+C 即收到SIGINT

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
#include <semaphore.h>

#define SHM_NAME "/shm"
#define SEM_1 "/sem_1"
#define SEM_2 "/sem_2"
#define SEM_3 "/sem_3"

static volatile sig_atomic_t run;

struct sharedMemory{
    int done;
};
static struct sharedMemory *shared;

static void handleSIGINT(int sig){
    if(sig == SIGINT){
       printf(" SIGINT caught: sig = %d\n", sig);
       shared->done = 1;
       run = 1;
    }
}

int main(int argc, char *argv[])
{
    // setup shared memory and semaphores
    int shmfd = shm_open(SHM_NAME, O_RDWR | O_CREAT, 0600);
    if (shmfd == -1){
        // handle error 
    }

    if (ftruncate(shmfd, sizeof(struct sharedMemory)) == -1){
        // handle error 
    }

    shared = mmap(NULL, sizeof(*shared), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
    if (shared == MAP_FAILED){
       // close resources
    }

    sem_t *sem_read = sem_open(SEM_1, O_CREAT | O_EXCL, 0600, 0);
    sem_t *sem_write = sem_open(SEM_2, O_CREAT | O_EXCL, 0600, BUFFER_SIZE);
    // sem open error handling
    if (sem_read == SEM_FAILED)
       // close resources 

    if (sem_write == SEM_FAILED)
       // close resources 

    // settup signal handler
    signal(SIGINT, handleSIGINT);

    while (!run)
    {
        sem_wait(sem_read);

        // read from shared memory and store data or set shared->done to 1 to stop generator process

        sem_post(sem_write);
    }

    // close resources
    printf("exiting\n");
    exit(EXIT_SUCCESS);
}

Ctrl+C 被按下时,volatile run 设置为 1 并且它跳出循环并退出。这在没有共享内存和信号量的情况下工作正常,但在这里我从来没有在stdout 上得到exiting 字符串,只有SIGINT caught: sig = 2 并且它继续运行。

为什么?

【问题讨论】:

    标签: c signals posix semaphore shared-memory


    【解决方案1】:

    您看到的行为的原因是信号处理程序的安装方式:

    signal(SIGINT, handleSIGINT);
    

    默认情况下,signal 启用 SA_RESTART 标志。这意味着sem_wait 将在调用信号处理程序后重新启动。

    这是使用sigaction 而不是signal 的主要原因之一。将上面的行更改为下面的代码,它应该可以按您的要求工作。

    struct sigaction saction;
    saction.sa_handler = handleSIGINT;
    sigemptyset(&saction.sa_mask);
    saction.sa_flags = 0;
    sigaction (SIGINT, &saction, NULL);
    

    不是您问题的直接部分,但建议在 SEM_1SEM_2 上调用 sem_unlink,并检查 sem_open 调用的返回值。由于O_EXCL 是在sem_open 中设置的,如果在使用kill 强制终止先前的调用后再次运行程序,它将失败。

    【讨论】:

    • 我故意忽略了错误处理部分,以使问题更集中于我的主要问题,但感谢您提醒我补充! unlinkingclosing 是我对 //close resources 评论的意思。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-27
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多