当前位置: 首页 > 知识库问答 >
问题:

用共享内存和信号量处理SIGINT

屠嘉
2023-03-14

我尝试编写一个共享内存和信号量程序,该程序一直运行到按下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时,volatilerun被设置为1,它会跳出循环并退出。在没有共享内存和信号量的情况下,这可以很好地工作,但是在这里,我从来没有在stdout上获得exiting字符串,只捕获sigint:sig=2并且它继续运行。

为什么?

共有1个答案

籍光熙
2023-03-14

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

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终止前一次调用后再次运行该程序,它将失败。

 类似资料:
  • 程序应该创建200000个整数,并将2000个写入共享内存。分叉进程应该从共享内存中读取2000,父进程应该将下一个2000写入共享内存。 请帮帮我们谢谢你们 编辑:非常感谢您的回答。我不能标出正确的答案,因为我不知道什么是正确的。但我不想再尝试了。15个小时就够了

  • 我想创建一个共享内存和信号量的C程序。应该有两个子进程。两个孩子都有一个不同的int数。然后有一个目标号码,应该写在共享内存中。现在两个孩子都应该从进球数中减去他们的数字,直到进球数低于或等于0。我不希望出现比赛条件。这就是为什么我尝试使用信号量。但对我没用。下面是我的代码:

  • 我需要编写一个程序,它正在创建N个数量的子进程,每一个进程都将一个添加到共享内存变量中。我的想法是使用信号量和共享内存,但进程之间并没有相互等待,共享内存变量也没有像我希望的那样工作。 MyDefs.H Main.C 奴隶Proc.c

  • null 有3个信号量:互斥-初始化为1满-初始化为0空-初始化为n(而n是管道中的“字节”数) 消费者代码: 生产者代码: 如有任何帮助,不胜感激,谢谢!