【发布时间】:2021-03-05 04:22:48
【问题描述】:
我正在使用sem_wait() 作为 IPC 应用程序的一部分,但我想要
等待被 ctrl-C 中断,如果出现则继续程序
有时候是这样的。但是,目前,任何信号都会终止我的程序。
sem_wait 手册页说“sem_wait() 函数是可中断的
通过传递信号。”所以我希望到达标记的线
### 和 result == EINTR 当我按 ctrl-C 或以其他方式发送此
处理一个信号。但就目前而言,我不这样做:程序只是
以通常的信号相关消息终止。
我大概必须以某种方式更改信号处理程序,但是如何?我尝试定义void handler(int){} 并使用signal(SIGINT, handler) 注册它。这当然可以防止终止,但它不会神奇地使 sem_wait() 可中断——大概我应该在注册期间或在处理程序本身中做一些不同的事情。
如果这有什么不同的话,我使用的是 Ubuntu 20.04 LTS 和 macOS 10.13.6。
/* Welcome to `semtest.c`. Compile with::
*
* gcc semtest.c -o semtest # Darwin
* gcc semtest.c -o semtest -pthread # Linux
*
* Run with::
*
* ./semtest wait
*
* Terminate by either (a) sending a signal (ctrl-c or `kill`)
* or (b) running `./semtest post`
*/
#include <string.h>
#include <stdio.h>
#include <semaphore.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For S_* mode constants */
#include <unistd.h> /* For getpid() */
int main(int argc, const char * argv[])
{
sem_t * semaphore = NULL;
char cmd;
int result;
if(argc == 2 && !strcmp(argv[1], "wait")) cmd = argv[1][0];
else if(argc == 2 && !strcmp(argv[1], "post")) cmd = argv[1][0];
else return fprintf(stderr, "usage: %s wait\n or: %s post", argv[0], argv[0]);
# define SEMAPHORE_NAME "/test"
fprintf(stderr, "%s is running with PID %d\n", argv[0], getpid());
if(cmd == 'w')
{
sem_unlink(SEMAPHORE_NAME);
semaphore = sem_open(SEMAPHORE_NAME, O_CREAT, (S_IRUSR | S_IWUSR), 0);
if(semaphore == SEM_FAILED)
return fprintf(stderr, "failed to create/open semaphore \"%s\" - sem_open() failed with error %d\n", SEMAPHORE_NAME, errno);
fprintf(stderr, "waiting for semaphore \"%s\"...\n", SEMAPHORE_NAME);
errno = 0;
/* signal(SIGINT, something...? ); */
result = sem_wait(semaphore);
/* ### Want to reach this line with result==EINTR when signal arrives */
fprintf(stderr, "sem_wait() returned %d (errno is %d)\n", result, errno);
sem_close(semaphore);
}
if(cmd == 'p')
{
semaphore = sem_open(SEMAPHORE_NAME, O_CREAT, (S_IRUSR | S_IWUSR), 0);
if(semaphore == SEM_FAILED)
return fprintf(stderr,"failed to create/open semaphore \"%s\" - sem_open() failed with error %d\n", SEMAPHORE_NAME, errno);
fprintf(stderr, "posting semaphore \"%s\"\n", SEMAPHORE_NAME);
errno = 0;
result = sem_post(semaphore);
if(result) fprintf(stderr, "sem_post() failed with return code %d (errno is %d)\n", result, errno);
sem_close(semaphore);
}
return 0;
}
【问题讨论】:
-
我大概必须以某种方式更改信号处理程序,但是如何?就是这样。那么你真的在问如何为 ctrl-c 编写和设置信号处理程序吗?
-
继续阅读
sigaction()。 -
您忘记阅读 signal(7) 和 signal-safety(7) 和 sigaction(2)。你可以在 Linux 上使用 signalfd(2) 和 poll(2)
-
@kaylum 是也不是。事实上,我已经阅读了 signal(7) 并尝试注册一个空的信号处理程序。它只是阻止了终止,没有中断
sem_wait()。我想我对一个什么都不做的处理程序一无所获并不感到惊讶,所以我认为这个尝试不值得一提,并假设我需要在处理程序中做一些特别的事情。但我使用signal()注册它,我想我没有意识到signal()和sigaction()之间的关键区别。