标题Linux下进程通讯之信号量集
1.简介
2.工作原理
3. 二值信号量
4. 查看系统信号量命令
1.查看信号量组:ipcs -s
[wbyq@wbyq 0414work]$ ipcs -s
--------- 信号量数组 -----------
键 semid 拥有者 权限 nsems
0xd2350092 3 wbyq 666 1
2.查看信号量限制信息:ipcs -ls
[wbyq@wbyq 0414work]$ ipcs -ls
--------- 信号量限制 -----------
最大数组数量 = 32000
每个数组的最大信号量数目 = 32000
系统最大信号量数 = 1024000000
每次信号量调用最大操作数 = 500
信号量最大值=32767
3.查看信号量详细信息:ipcs -s -i <semid>
[wbyq@wbyq 0414work]$ ipcs -s -i 3
信号量数组 semid=3
uid=1000 gid=1000 cuid=1000 cgid=1000
模式=0666,访问权限=0666
nsems = 1
otime = Fri Apr 29 10:27:21 2022
ctime = Fri Apr 29 10:25:28 2022
semnum 值 ncount zcount pid
0 1 0 0 13747
4.创建信号量:ipcmk -S <信号量个数>
//创建信号量,信号量个数为5个
[wbyq@wbyq 0414work]$ ipcmk -S 5
信号量 id:6
//查看创建的信号量
[wbyq@wbyq 0414work]$ ipcs -s -i 6
信号量数组 semid=6
uid=1000 gid=1000 cuid=1000 cgid=1000
模式=0644,访问权限=0644
nsems = 5
otime = 未设置
ctime = Fri Apr 29 14:17:16 2022
semnum 值 ncount zcount pid
0 0 0 0 0
1 0 0 0 0
2 0 0 0 0
3 0 0 0 0
4 0 0 0 0
5.删除信号量:ipcrm -s <semid>
//删除信号量6
[wbyq@wbyq 0414work]$ ipcs -s 6
--------- 信号量数组 -----------
键 semid 拥有者 权限 nsems
0xd2350092 3 wbyq 666 1
0xa8132e52 4 wbyq 644 1
0x9416e553 6 wbyq 644 5
[wbyq@wbyq 0414work]$ ipcrm -s 6
//删除后结果
[wbyq@wbyq 0414work]$ ipcs -s
--------- 信号量数组 -----------
键 semid 拥有者 权限 nsems
0xd2350092 3 wbyq 666 1
0xa8132e52 4 wbyq 644 1
5.信号量相关函数
6.创建一个信号量示例
(1)创建信号量
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/sem.h>
union semun
{
int val; /* 信号量值 */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
};
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("格式:./a.out <信号量值>\n");
return 0;
}
key_t key=ftok("semget.c",1234);//产生键值
if(key==-1)
{
printf("产生键值失败res=%s\n",strerror(errno));
return 0;
}
printf("key=%#x\n",key);
int semid=semget(key,1,IPC_CREAT|0666);//创建1个信号量
if(semid==-1)
{
printf("创建信号量集失败res=%s\n",strerror(errno));
return 0;
}
printf("semid=%d\n",semid);
union semun sem;
sem.val=atoi(argv[1]);
/*初始化信号量*/
if(semctl(semid,0,SETVAL,sem))
{
printf("初始化信号量值失败err=%s\n",strerror(errno));
return 0;
}
/*获取信号量*/
int val=semctl(semid,0,GETVAL,NULL);
printf("信号量值:%d\n",val);
/*通过系统命令查看信号量详细信息*/
char buff[20];
snprintf(buff,sizeof(buff),"ipcs -s -i %d",semid);
system(buff);
return 0;
}
(2)使用信号量
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/sem.h>
union semun
{
int val; /* 信号量值 */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
};
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("格式:./a.out <使用信号值>\n");
return 0;
}
key_t key=ftok("semget.c",1234);//产生键值
if(key==-1)
{
printf("产生键值失败res=%s\n",strerror(errno));
return 0;
}
printf("key=%#x\n",key);
int semid=semget(key,1,IPC_CREAT|0666);//创建1个信号量
if(semid==-1)
{
printf("创建信号量集失败res=%s\n",strerror(errno));
return 0;
}
printf("semid=%d\n",semid);
/*获取信号量*/
int val=semctl(semid,0,GETVAL,NULL);
printf("信号量值:%d\n",val);
/*pv操作*/
struct sembuf sops=
{
.sem_num=0,//信号量下标
.sem_op=atoi(argv[1]),
.sem_flg=0//阻塞等待
};
int ret=semop(semid,&sops,1);
printf("ret=%d\n",ret);
/*获取信号量*/
val=semctl(semid,0,GETVAL,NULL);
printf("信号量值:%d\n",val);
return 0;
}
(3)运行效果
7.创建多个信号量
(1)创建多个信号量
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/sem.h>
union semun
{
int val; /* 信号量值 */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
};
int main(int argc,char *argv[])
{
if(argc!=4)
{
printf("格式:./a.out <信号量值1> <信号量值2> <信号量值3>\n");
return 0;
}
key_t key=ftok("semget.c",1234);//产生键值
if(key==-1)
{
printf("产生键值失败res=%s\n",strerror(errno));
return 0;
}
printf("key=%#x\n",key);
int semid=semget(key,3,IPC_CREAT|0666);//创建3个信号量
if(semid==-1)
{
printf("创建信号量集失败res=%s\n",strerror(errno));
return 0;
}
printf("semid=%d\n",semid);
union semun sem[3];
sem[0].val=atoi(argv[1]);//初始化第一个信号量
sem[1].val=atoi(argv[2]);//初始化第二个信号量
sem[2].val=atoi(argv[3]);//初始化第三个信号量
int i=0;
for(i=0;i<3;i++)
{
/*初始化信号量*/
if(semctl(semid,i,SETVAL,sem[i]))
{
printf("初始化信号量值失败err=%s\n",strerror(errno));
return 0;
}
/*获取信号量*/
int val=semctl(semid,i,GETVAL,NULL);
printf("第%d个信号量值:%d\n",i,val);
}
/*通过系统命令查看信号量详细信息*/
system("ipcs -s");
return 0;
}
(2)使用多个信号量
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/sem.h>
union semun
{
int val; /* 信号量值 */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
};
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("格式:./a.out <使用信号值>\n");
return 0;
}
key_t key=ftok("semget.c",1234);//产生键值
if(key==-1)
{
printf("产生键值失败res=%s\n",strerror(errno));
return 0;
}
printf("key=%#x\n",key);
int semid=semget(key,3,IPC_CREAT|0666);//创建3个信号量
if(semid==-1)
{
printf("创建信号量集失败res=%s\n",strerror(errno));
return 0;
}
printf("semid=%d\n",semid);
int i=0;
/*获取信号量*/
for(i=0;i<3;i++)
{
/*获取信号量*/
int val=semctl(semid,i,GETVAL,NULL);
printf("第%d个信号量值:%d\n",i,val);
}
/*pv操作*/
struct sembuf sops[3]=
{
{
.sem_num=0,//信号量下标
.sem_op=atoi(argv[1]),
.sem_flg=0//阻塞等待
},
{
.sem_num=1,//信号量下标
.sem_op=atoi(argv[1]),
.sem_flg=0//阻塞等待
},
{
.sem_num=2,//信号量下标
.sem_op=atoi(argv[1]),
.sem_flg=0//阻塞等待
}
};
int ret=semop(semid,sops,3);//一次使用3个信号量
printf("ret=%d\n",ret);
/*获取信号量*/
/*获取信号量*/
for(i=0;i<3;i++)
{
/*获取信号量*/
int val=semctl(semid,i,GETVAL,NULL);
printf("第%d个信号量值:%d\n",i,val);
}
return 0;
}
(3)运行效果