- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试通过 semop 调用引发 EINTR 失败。
key_t semkey;
int semid;
struct sembuf sbuf;
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
} arg;
struct semid_ds ds;
/* Get unique key for semaphore. */
if ((semkey = ftok("/tmp", 'a')) == (key_t) -1) {
perror("IPC error: ftok"); exit(1);
}
/* Get semaphore ID associated with this key. */
if ((semid = semget(semkey, 0, 0)) == -1) {
/* Semaphore does not exist - Create. */
if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR |
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1)
{
/* Initialize the semaphore. */
arg.val = 0;
sbuf.sem_num = 0;
sbuf.sem_op = 2; /* This is the number of runs without queuing. */
sbuf.sem_flg = 0;
if (semctl(semid, 0, SETVAL, arg) == -1
|| semop(semid, &sbuf, 1) == -1) {
perror("IPC error: semop"); exit(1);
}
}
else if (errno == EEXIST) {
if ((semid = semget(semkey, 0, 0)) == -1) {
perror("IPC error 1: semget"); exit(1);
}
goto check_init;
}
else {
perror("IPC error 2: semget"); exit(1);
}
}
else
{
/* Check that semid has completed initialization. */
/* An application can use a retry loop at this point rather than
exiting. */
check_init:
arg.buf = &ds;
if (semctl(semid, 0, IPC_STAT, arg) < 0) {
perror("IPC error 3: semctl"); exit(1);
}
if (ds.sem_otime == 0) {
perror("IPC error 4: semctl"); exit(1);
}
}
sbuf.sem_num = 0;
sbuf.sem_op = -1;
sbuf.sem_flg = SEM_UNDO;
while (semop(semid, &sbuf, 1) == -1)
{
if (errno != EINTR)
{
perror("IPC Error: semop"); exit(1);
break;
}
}
我得到的最多的是资源不可用失败或资源繁忙。我什至尝试在两个不同的线程或两个不同的进程中运行多个信号量。但我无法获得 EINTR 失败。当 semop 等待信号量时,我什至尝试将信号作为 SIGCHLD 发送到进程。
根据 zwol 的建议,
这是我尝试过的,但它仍然不起作用,我的意思是我无法获得 EINTR。
int g_global_variable = 0;
void *sigusr1_block_thread (void *vargp)
{
while (1)
{
sleep (10);
printf ("sigusr1_block_thread\n");
}
return NULL;
}
void *semop_wait_thread (void *vargp)
{
int sem;
struct sembuf sops[2];
if((sem = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600))==-1){
return NULL;
}
if(semctl(sem,0,SETVAL,2)==-1){
exit(1);
}
sops[0].sem_num=0;
sops[0].sem_op=-1;
sops[0].sem_flg=0;
sops[1].sem_num=0;
sops[1].sem_op=0;
sops[1].sem_flg=0;
g_global_variable = 1;
printf ("Starting semop call \n");
if(eintr_check_semop(sem, sops,2)<0)
printf("Error semop\n");
return NULL;
}
int main()
{
pthread_t tid, tid1, tid2, tid3, tid4;
sigset_t set;
int s;
pthread_create(&tid, NULL, semop_wait_thread, NULL);
pthread_create(&tid2, NULL, semop_wait_thread, NULL);
pthread_create(&tid3, NULL, semop_wait_thread, NULL);
pthread_create(&tid4, NULL, semop_wait_thread, NULL);
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGCHLD);
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
printf ("Error during pthread_sigmask");
pthread_create(&tid1, NULL, sigusr1_block_thread, NULL);
while (1)
{
sleep (1);
if (g_global_variable == 1)
{
sleep (10);
printf ("Send SIGUSR1/SIGCHLD signals \n");
/* Send signal */
pthread_kill( tid, SIGCHLD);
pthread_kill( tid2, SIGCHLD);
pthread_kill( tid3, SIGCHLD);
pthread_kill( tid4, SIGCHLD);
pthread_kill( tid1, SIGCHLD);
pthread_kill( tid1, SIGUSR1);
break;
}
else
continue;
}
pthread_join(tid, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
pthread_join(tid4, NULL);
return 0;
}
eintr_check_semop 只是一个检查 semop 错误和返回值的函数。如果 EINTR 它会打印相同的消息。
如果我将 sigusr1 发送到阻塞线程(t、t2、t3、t4)semop 调用中断并进入循环。
无论如何我都没有得到 EINTR。然后我检查了内核源代码。
https://elixir.bootlin.com/linux/latest/source/ipc/sem.c
在 EINTR 期间,我看到它们正在循环并且没有报告相同的情况。
最佳答案
EINTR
仅当进程在阻塞系统调用上被阻塞时接收到信号,并且该信号具有处理程序,并且该处理程序配置为中断而不是重新启动系统调用时,才会发生。 (这个原则有一些异常(exception),但它们都不涉及semop
。)你的程序没有任何信号处理程序,所以EINTR不会发生,即使如果你确实向它发送信号。
我无法直接告诉你如何做到这一点,但应该有效的总体模式是:
为某些信号建立信号处理程序。如果您没有理由选择其他特定信号,请使用 SIGUSR1
。使用 sigaction
来执行此操作,而不是 signal
,并且不要在 sa_flags
中包含 SA_RESTART
。处理程序无需执行任何操作;它必须存在。
如果程序有多个线程,请使用 pthread_sigmask
阻止除一个线程之外的每个线程中的 SIGUSR1
。
在已解除阻塞的 SIGUSR1
线程中,执行将阻塞的 semop
操作(对具有非零值的信号量进行“等待零”操作)值,没有 IPC_NOWAIT
)。
在上述线程在 semop
上肯定被阻塞之后,从程序中的另一个线程,使用 pthread_kill
发送 SIGUSR1
到被阻止的线程。或者,从程序外部,使用常规 kill
向整个进程发送 SIGUSR1
;因为信号在一个线程中被解除阻塞,所以该线程将接收到该信号。
最难的部分是确保在发送信号之前线程在 semop
上被阻塞。我不确定在没有竞争条件的情况下这是否可以从程序内部实现。
关于c - 如何在linux中引发因EINTR而失败的semop调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50065805/
我在一个进程中有两个线程。这两个线程竞争共享内存,试图通过信号量进行同步。但是,当一个线程紧挨着另一个线程调用 semop 函数时,我随机遇到了 errno 4 失败。我做了一点挖掘,发现调用似乎被系
我正在创建一个多进程应用程序,其中包含一个共享内存段和一个锁定它的信号量以及信号处理程序。 每当我锁定和解锁我的信号量时,一切正常,只要它在我的主程序(或其中一个子程序)中。 当我在信号处理程序中时出
关于Beej Guide ,有一个说法如下 “当您第一次创建一些信号量时,它们都未初始化;需要再次调用才能将它们标记为空闲。” 最初我创建的信号量计数为 5。 #define SEM_COUNT 5
我在进程 A 中设置了(semget + init 为 1)一个信号量。 fork A,并得到 B。 fork B 并得到 C(进程 B、C 的代码位于另一个 .c 文件中,因此我使用 extern
我有这段代码,它基本上在信号量上生成一个 P,编号为 sem。信号量在池中。问题是有时我得到 Invalid argument 并且我不知道为什么。 bool sem_p(key_t key, int
当尝试运行此代码时:首先它会为每个信号量打印“Process some_id BEFORE enter”(2 次)。然后它挂起。哪里不对? # include # include # includ
#define MAX 2 int main(){ int mutex = semget(ftok("/usr",'P'),1,IPC_CREAT|0666); int wrt = s
我在 php 脚本中使用以下代码片段来安全地更新共享资源。 $lock_id = sem_get( ftok( 'tmp/this.lock', 'r')); sem_acquire($lock_id
我有两个信号量应该自动更改。 union semun su; struct sembuf sb[2]; int num = 2; semid = semget(num, 3, IPC_
这段代码我真的遇到了麻烦。我有一个缓冲区和一个方法 Produce() ,它应该是非阻塞的,这意味着当许多进程尝试 Produce() 时,除了一个进程之外,所有这些进程都应该返回/或失败。 我在 m
正如您在信号量 System V 文档 ( http://man7.org/linux/man-pages/man2/semop.2.html ) 中看到的,有一部分声明了以下内容: EXAMPLE
我正在使用 Sys V Semaphores 测试一些代码,以了解其从各种事件中恢复的能力,对于其中一项测试,我在进程处于其关键部分时删除了信号量集(从终端)。当需要再次调用 semop 来释放锁时,
我正在检查 semop() 函数,结构 sembuf 的标志值可能是 SEM_UNDO 或 IPC_NOWAIT。那么如果我们将标志值作为 0 传递,那么行为会是什么?我在某处读到它是没有操作的。这意
我正在研究 Beej's Guide to Unix IPC 中的信号量示例程序. 示例程序包含以下信号量初始化代码。我只是从中发布与问题相关的片段。要查看完整代码,请访问我在上面提供的链接。 /*
fork 中的这一行(doc)引起了我的注意: 子项不会从其父项 (semop(2)) 继承信号量调整。 这是什么意思? 这个程序(下面的代码)永远不会打印“End (child)”: #defin
因此,如果我有一个信号量集 semid,带有num_of_sems 个信号量和一个sembuf *deleter_searchers_down struct sembuf *deleter_searc
我有一个代码,我正在处理一组 3 个信号量。我有两套struct sembuf wait[3],signal[3]; 我已经初始化了它们中的每一个。 wait初始化为-1,signal初始化为1 然后
我是一名优秀的程序员,十分优秀!