linux下多进程信号量使用问题,解决两个进程同时获取到资源..

时间:2022-10-11 16:43:52
为了解决我那该死的3个进程同时连接数据库问题..我现在使用信号量碰到了问题
信号量初始资源为1,3个进程同时执行到semop函数,然后一个进程获得了资源.另外两个进程等待,但在第1个进程释放资源后,另外2个进程都获取到了资源,然后2个进程就都往下执行了..
我希望的是semop下面的代码,同时只有1个进程在执行,另外2个进程等待

key_t key;
  key = ftok("/", 0);

int semid = semget(key, 1, IPC_CREAT| IPC_EXCL |0666);
if (semid == -1)
{
semid = semget(key, 1, IPC_EXCL |0666);//信号量已存在
}
else
semctl(semid, 0, SETVAL, 1); /*设置索引0的信号量*/
   
int getvalue = semctl(semid, 0, GETVAL, 0);
struct sembuf acquire = {0, -1, SEM_UNDO};
struct sembuf release = {0, 1, SEM_UNDO};

         
         if (-1 == semop(semid,&acquire,1))//第1个进程释放资源后,另外2个进程都不再阻塞这这里了,需要解决
{
return 0;
}
         

         ...... //代码块,同一时刻只能1个进程执行
         semop(semid,&release,1);

13 个解决方案

#1


跟踪一下semid的值是多少
另外,最好不要这么定义struct sembuf acquire = {0, -1, SEM_UNDO};
也许你的系统中sembuf各个成员的顺序和你预期的不一致

#2


引用 1 楼 justkk 的回复:
跟踪一下semid的值是多少
另外,最好不要这么定义struct sembuf acquire = {0, -1, SEM_UNDO};
也许你的系统中sembuf各个成员的顺序和你预期的不一致

semid 都是一样的.
我的问题是这样的,程序执行步骤
1:3个进程都创建或打开同一个信号量
2:初始化信号量资源为1
3:进程1获得了资源,进程2和进程3等待
4:进程1是否资源,进程1退出
5:在进程1是否资源后,进程2和进程3同时不再阻塞了,往下执行..

问题就在第5部,应该让进程2和进程3,在进程1释放信号量时,只能是进程2获取资源然后执行,进程3依然等待直到进程2释放资源

#3


确认一下,是不是3个进程都执行了semctl(semid, 0, SETVAL, 1);
这样,即使一个进程获取了信号灯,值为0了,另外一个进程还是把它的值重新设置为1了

#4


只有1个进程执行了semctl(semid, 0, SETVAL, 1);
因为我在semop之前打印出来了资源数
int getvalue = semctl(semid, 0, GETVAL, 0);
printf("sem value is %d ", getvalue);
打印出来第1个进程为1,其他2个进程都为0

#5


进程1操作完成之后,进程退出了吗?

#6


引用 5 楼 justkk 的回复:
进程1操作完成之后,进程退出了吗?

实际上是进程1的1个线程执行这块代码的。执行完后这个线程就退出了。但是进程1,2,3都是一直运行的
3个进程是同一份代码

#7


会不会与SEM_UNDO标志有关?

#8


引用 7 楼 justkk 的回复:
会不会与SEM_UNDO标志有关?

我今天再试试!我对信号量不熟!

#9


跟SEM_UNDO标识没关系

#10


引用 4 楼 honemay 的回复:
只有1个进程执行了semctl(semid, 0, SETVAL, 1);

你说3个进程是同一份代码,那应该都执行这个semctl 了啊..

你每次执行都是一样的结果吗?
要不你把完整代码贴上来看看?

#11


引用 10 楼 justkk 的回复:
引用 4 楼 honemay 的回复:
只有1个进程执行了semctl(semid, 0, SETVAL, 1);

你说3个进程是同一份代码,那应该都执行这个semctl 了啊..

你每次执行都是一样的结果吗?
要不你把完整代码贴上来看看?

完整代码实际上前面的那部分就是了,这只是整个程序中的一个线程函数而已.
semctl 只会执行一次啊,因为第1个进程创建了信号量,第2,3个线程就会创建失败,然后它们就做打开信号量的操作..
我放弃了,不搞了,我现在打算重新编译我的mysql数据库,因为我做这个信号量的步骤就是为了解决3个进程同时connect mysql的时候进程会死掉的问题。
只能把Mysql客户端编译成安全的。。

#12


第2、3个进程使用semget打开信号量,但是他们也执行semctl 了

#13


引用 12 楼 justkk 的回复:
第2、3个进程使用semget打开信号量,但是他们也执行semctl 了

但是我打印出来,第2,3个进程的信号量的值都为0..

#1


跟踪一下semid的值是多少
另外,最好不要这么定义struct sembuf acquire = {0, -1, SEM_UNDO};
也许你的系统中sembuf各个成员的顺序和你预期的不一致

#2


引用 1 楼 justkk 的回复:
跟踪一下semid的值是多少
另外,最好不要这么定义struct sembuf acquire = {0, -1, SEM_UNDO};
也许你的系统中sembuf各个成员的顺序和你预期的不一致

semid 都是一样的.
我的问题是这样的,程序执行步骤
1:3个进程都创建或打开同一个信号量
2:初始化信号量资源为1
3:进程1获得了资源,进程2和进程3等待
4:进程1是否资源,进程1退出
5:在进程1是否资源后,进程2和进程3同时不再阻塞了,往下执行..

问题就在第5部,应该让进程2和进程3,在进程1释放信号量时,只能是进程2获取资源然后执行,进程3依然等待直到进程2释放资源

#3


确认一下,是不是3个进程都执行了semctl(semid, 0, SETVAL, 1);
这样,即使一个进程获取了信号灯,值为0了,另外一个进程还是把它的值重新设置为1了

#4


只有1个进程执行了semctl(semid, 0, SETVAL, 1);
因为我在semop之前打印出来了资源数
int getvalue = semctl(semid, 0, GETVAL, 0);
printf("sem value is %d ", getvalue);
打印出来第1个进程为1,其他2个进程都为0

#5


进程1操作完成之后,进程退出了吗?

#6


引用 5 楼 justkk 的回复:
进程1操作完成之后,进程退出了吗?

实际上是进程1的1个线程执行这块代码的。执行完后这个线程就退出了。但是进程1,2,3都是一直运行的
3个进程是同一份代码

#7


会不会与SEM_UNDO标志有关?

#8


引用 7 楼 justkk 的回复:
会不会与SEM_UNDO标志有关?

我今天再试试!我对信号量不熟!

#9


跟SEM_UNDO标识没关系

#10


引用 4 楼 honemay 的回复:
只有1个进程执行了semctl(semid, 0, SETVAL, 1);

你说3个进程是同一份代码,那应该都执行这个semctl 了啊..

你每次执行都是一样的结果吗?
要不你把完整代码贴上来看看?

#11


引用 10 楼 justkk 的回复:
引用 4 楼 honemay 的回复:
只有1个进程执行了semctl(semid, 0, SETVAL, 1);

你说3个进程是同一份代码,那应该都执行这个semctl 了啊..

你每次执行都是一样的结果吗?
要不你把完整代码贴上来看看?

完整代码实际上前面的那部分就是了,这只是整个程序中的一个线程函数而已.
semctl 只会执行一次啊,因为第1个进程创建了信号量,第2,3个线程就会创建失败,然后它们就做打开信号量的操作..
我放弃了,不搞了,我现在打算重新编译我的mysql数据库,因为我做这个信号量的步骤就是为了解决3个进程同时connect mysql的时候进程会死掉的问题。
只能把Mysql客户端编译成安全的。。

#12


第2、3个进程使用semget打开信号量,但是他们也执行semctl 了

#13


引用 12 楼 justkk 的回复:
第2、3个进程使用semget打开信号量,但是他们也执行semctl 了

但是我打印出来,第2,3个进程的信号量的值都为0..