【发布时间】:2012-04-03 16:38:12
【问题描述】:
这是一个奇怪的问题。我先初始化sem并破坏它,然后我在一个线程中再次初始化它。然后,我无法再次唤醒它。代码是:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
sem_t sem;
int key = 1;
static void *
wait_func()
{
printf("i'm wait\n");
sem_wait(&sem);
}
static void *
cancel_func(void *arg)
{
pthread_t tid = *(pthread_t *)arg;
if (key == 1)
{
sleep(1);
key = 0;
}
else
sleep(3);
if(pthread_cancel(tid) == 0)
printf("cancle!\n");
sem_init(&sem, 0, 0);
sem_destroy(&sem);
}
int
main(int argc, char *argv[])
{
pthread_t wthread, cthread;
pthread_attr_t attr;
int i = 0;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
sem_init(&sem, 0, 0);
while (i < 2)
{
// sem_init(&sem, 0, 0);
pthread_create(&wthread, &attr, wait_func, NULL);
if (i < 1)
pthread_create(&cthread, &attr, cancel_func, &wthread);
if (key == 0)
{
sleep(2);
if (sem_post(&sem) == 0)
printf("post!\n");
key = 1;
}
sleep(4);
++i;
}
sleep(1000);
}
然而,在 while 循环中改变 sem_init 就像评论一样!所以我跟踪了两个程序,发现 1) 在线程中初始化,sem_post 没有调用 sys_futex,像这样:
nanosleep({2, 0}, i'm wait
{2, 0}) = 0 写(1,“发布!\ n”,6发布! ) = 6
2)在主进程初始化,sem_post调用sys_futex,如下:
nanosleep({2, 0}, i'm wait
{2, 0}) = 0 futex(0x600dc0, FUTEX_WAKE_PRIVATE, 1) = 1 写(1,“发布!\ n”,6发布! ) = 6
然后,我想这可能是系统调用的问题。我使用 gdb 反汇编了 sem_post 中的两个程序。不幸的是,1)在线程中初始化,它也在sem_post中调用了syscall;2)比较了它们的注册表状态,其中rip是syscall,也是如此。
in thread:
rax 0xca 202 //sys_futex
rbx 0x3c0e61bbc0 257939323840
rcx 0x0 0 //utime
rdx 0x1 1 //val
rsi 0x81 129 //op:private_wake
rdi 0x600dc0 6294976 //sem uaddr
in main process:
rax 0xca 202
rbx 0x3c0e61bbc0 257939323840
rcx 0x0 0
rdx 0x1 1
rsi 0x81 129
rdi 0x600da0 6294944
最后,我不知道这个问题。请给我一些建议以找出解决方案,谢谢。
【问题讨论】:
-
这是一个实际问题吗?如果您不不断地创建和销毁信号量,就没有问题,对吧?除此之外,使用共享键状态变量、短睡眠和多线程,我不知道您的代码实际上在做什么。很抱歉,我准备被纠正,但这听起来像是“我正在用信号量做一些不切实际和奇怪的事情,而且我的行为很奇怪”。如果你创建了信号量并且不销毁它,你就可以了,是吗?
-
是的,每次使用我的示例代码时都会重复。我读了一些 sem_init 的手册页说不要在许多线程中初始化相同的 sem,但是,我不太清楚sem 指向一个 uaddr 或初始化一个 sem var 两次。代码无所事事,只会让 sem_wait 满足。跟踪它确实调用 syscall(futex_wake) 的汇编代码,但 strace 不会转储这个 syscall,这很奇怪。
标签: c linux multithreading posix semaphore