导航:首页 > 操作系统 > linux信号量的使用

linux信号量的使用

发布时间:2024-06-23 09:56:42

A. linux信号量

信号量是包含一个非负整数型的变量,并且带有两个原子操作wait和signal。Wait还可以被称为down、P或lock,signal还可以被称为up、V、unlock或post。在UNIX的API中(POSIX标准)用的是wait和post。

对于wait操作,如果信号量的非负整形变量S大于0,wait就将其减1,如果S等于0,wait就将调用线程阻塞;对于post操作,如果有线程在信号量上阻塞(此时S等于0),post就会解除对某个等待线程的阻塞,使其从wait中返回,如果没有线程阻塞在信号量上,post就将S加1.

由此可见,S可以被理解为一种资源的数量,信号量即是通过控制这种资源的分配来实现互斥和同步的。如果把S设为1,那么信号量即可使多线程并发运行。另外,信号量不仅允许使用者申请和释放资源,而且还允许使用者创造资源,这就赋予了信号量实现同步的功能。可见信号量的功能要比互斥量丰富许多。

POSIX信号量是一个sem_t类型的变量,但POSIX有两种信号量的实现机制: 无名信号量 命名信号量 。无名信号量只可以在共享内存的情况下,比如实现进程中各个线程之间的互斥和同步,因此无名信号量也被称作基于内存的信号量;命名信号量通常用于不共享内存的情况下,比如进程间通信。

同时,在创建信号量时,根据信号量取值的不同,POSIX信号量还可以分为:

下面是POSIX信号量函数接口:

信号量的函数都以sem_开头,线程中使用的基本信号函数有4个,他们都声明在头文件semaphore.h中,该头文件定义了用于信号量操作的sem_t类型:

【sem_init函数】:

该函数用于创建信号量,原型如下:

该函数初始化由sem指向的信号对象,设置它的共享选项,并给它一个初始的整数值。pshared控制信号量的类型,如果其值为0,就表示信号量是当前进程的局部信号量,否则信号量就可以在多个进程间共享,value为sem的初始值。

该函数调用成功返回0,失败返回-1。

【sem_destroy函数】:

该函数用于对用完的信号量进行清理,其原型如下:

成功返回0,失败返回-1。

【sem_wait函数】:

该函数用于以原子操作的方式将信号量的值减1。原子操作就是,如果两个线程企图同时给一个信号量加1或减1,它们之间不会互相干扰。其原型如下:

sem指向的对象是sem_init调用初始化的信号量。调用成功返回0,失败返回-1。

sem_trywait()则是sem_wait()的非阻塞版本,当条件不满足时(信号量为0时),该函数直接返回EAGAIN错误而不会阻塞等待。

sem_timedwait()功能与sem_wait()类似,只是在指定的abs_timeout时间内等待,超过时间则直接返回ETIMEDOUT错误。

【sem_post函数】:

该函数用于以原子操作的方式将信号量的值加1,其原型如下:

与sem_wait一样,sem指向的对象是由sem_init调用初始化的信号量。调用成功时返回0,失败返回-1。

【sem_getvalue函数】:

该函数返回当前信号量的值,通过restrict输出参数返回。如果当前信号量已经上锁(即同步对象不可用),那么返回值为0,或为负数,其绝对值就是等待该信号量解锁的线程数。

【实例1】:

【实例2】:

之所以称为命名信号量,是因为它有一个名字、一个用户ID、一个组ID和权限。这些是提供给不共享内存的那些进程使用命名信号量的接口。命名信号量的名字是一个遵守路径名构造规则的字符串。

【sem_open函数】:

该函数用于创建或打开一个命名信号量,其原型如下:

参数name是一个标识信号量的字符串。参数oflag用来确定是创建信号量还是连接已有的信号量。

oflag的参数可以为0,O_CREAT或O_EXCL:如果为0,表示打开一个已存在的信号量;如果为O_CREAT,表示如果信号量不存在就创建一个信号量,如果存在则打开被返回,此时mode和value都需要指定;如果为O_CREAT|O_EXCL,表示如果信号量存在则返回错误。

mode参数用于创建信号量时指定信号量的权限位,和open函数一样,包括:S_IRUSR、S_IWUSR、S_IRGRP、S_IWGRP、S_IROTH、S_IWOTH。

value表示创建信号量时,信号量的初始值。

【sem_close函数】:

该函数用于关闭命名信号量:

单个程序可以用sem_close函数关闭命名信号量,但是这样做并不能将信号量从系统中删除,因为命名信号量在单个程序执行之外是具有持久性的。当进程调用_exit、exit、exec或从main返回时,进程打开的命名信号量同样会被关闭。

【sem_unlink函数】:

sem_unlink函数用于在所有进程关闭了命名信号量之后,将信号量从系统中删除:

【信号量操作函数】:

与无名信号量一样,操作信号量的函数如下:

命名信号量是随内核持续的。当命名信号量创建后,即使当前没有进程打开某个信号量,它的值依然保持,直到内核重新自举或调用sem_unlink()删除该信号量。

无名信号量的持续性要根据信号量在内存中的位置确定:

很多时候信号量、互斥量和条件变量都可以在某种应用中使用,那这三者的差异有哪些呢?下面列出了这三者之间的差异:

B. linux 信号量是什么怎么用

Linux信号量(semaphore)是一种互斥机制。即对某个互斥资源的访问会收到信号量的保护,在访问之前需要获得信号量。
在操作完共享资源后,需释放信号量,以便另外的进程来获得资源。获得和释放应该成对出现。
获得信号量集,需要注意的是,获得的是一个集合,而不是一个单一的信号量。
#include
#include
#include
1: int semget(key_t key,int nsems,int semflg);
key:系统根据这个值来获取信号量集。
nsems:此信号集包括几个信号量。
semflg:创建此信号量的属性。 (IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)
成功则返回该信号量集的ID。
注:
既指定IPC_CREAT又指定IPC_EXCL时,如果系统中该信号量集已经存在,则马上返回。
如果需要获得存在的信号量,则将此参数置0.
2: int semctl(int semid,int senum,int cmd....)
semid:信号量ID。
senum:对信号量集中的第几个信号量进行控制。(从0开始)
cmd:需要进行的操作。(SETVAL是其中的一个)。
根据cmd的不同可能存在第四个参数,cmd=SETVAL时,表示同时信号量可以被获得几次,如第四个参数
num=1表示只能被获得一次,既被信号量保护的资源只能同时被一个程序使用。
该系统调用,是在对信号量初始化时用的。
-3: “3”前面加了"-"表示当需要使用互斥资源时应该做这步。
int semop(int semid,struct sembuf *sem,int num_elements);
struct sembuf {
unsigned short sem_num; //该信号量集中的第几个信号量。
int sem_op;//需要获得还是释放信号量
int sem_flg;//相关动作
};
num_elements:需要对该信号量集中的多少个信号量进行处理。
获得信号量时,将sembuf结构提初始化为:
sem_num = 0; //该信号量集中的首个信号量
sem_op = -1; //获得信号量
sem_flag = IPC_NOWAIT; //如果不能获得信号量,马上返回。
semop(semid,_sem,1);
同理释放信号量时,将sem_op设为1.
以上是对信号量的简单处理

C. 濡备綍鍦↙inux涓阃氲繃semget鍜宻emctl鍑芥暟鍒嗛厤骞堕喷鏀句俊鍙烽噺锛

Linux 绯荤粺涓锛屼俊鍙烽噺镄勭$悊阃氲繃 semget 鍜 semctl 杩欎袱涓绯荤粺璋幂敤𨱒ュ畬鎴愶纴瀹冧滑镄勪綔鐢ㄧ被浼间簬 shmget 鍜 shmctl 瀵瑰叡浜鍐呭瓨镄勫勭悊銆傝佷娇鐢ㄤ俊鍙烽噺锛屼綘闇瑕侀栧厛璋幂敤 semget 鍑芥暟锛屼紶鍏ュ弬鏁板寘𨰾淇″彿閲忕粍镄勯敭鍊笺佷俊鍙烽噺镄勬暟閲忎互鍙婃潈闄愭爣璇嗐傞敭鍊肩敤浜庡敮涓镙囱瘑淇″彿閲忕粍锛屽嵆浣胯繘绋嬮鍑猴纴淇″彿閲忎篃浼氩湪绯荤粺涓鎸佷箙瀛桦湪銆傝幏鍙栧凡瀛桦湪镄勪俊鍙烽噺镞讹纴鍙浠ヤ紶鍏0浣滀负缁勫归噺銆


淇″彿閲忕殑鐢熷懡锻ㄦ湡闇瑕佹坠锷ㄧ$悊锛屽綋链钖庝竴涓浣跨敤淇″彿閲忕殑杩涚▼阃鍑烘椂锛岄渶瑕佽皟鐢 semctl 鍑芥暟𨱒ュ垹闄や俊鍙烽噺缁勚傝繖涓鍑芥暟闇瑕佸洓涓鍙傛暟锛氢俊鍙烽噺缁勬爣璇嗙︺佽佹搷浣灭殑淇″彿閲忕紪鍙凤纸鍦ㄨ繖涓渚嫔瓙涓鏄1锛夈佸父閲 IPC_RMID 鍜屼竴涓 union semun 绫诲瀷镄勭粨鏋勪綋锛埚疄闄呮搷浣滀腑蹇界暐锛夈傚垹闄ゆ搷浣滆佹眰璋幂敤钥呬笌淇″彿閲忕粍鍒涘缓钥呮潈闄愮浉钖岋纴鎴栬呮嫢链 root 𨱒冮檺銆备笌 shmget 涓嶅悓锛屽垹闄や俊鍙烽噺缁勪细绔嫔嵆閲婃斁绯荤粺璧勬簮銆


鍦ㄤ唬镰佸眰闱锛屽备唬镰 5.2锛坰em_all_deall.c锛夋墍绀猴纴链変袱涓鍏抽敭鍑芥暟锛氢竴涓鐢ㄤ簬鍒嗛厤浜屽厓淇″彿閲忥纸binary_semaphore_allocation锛夛纴阃氲繃 semget 鍑芥暟銮峰彇鎴栧垱寤猴绂鍙︿竴涓鐢ㄤ簬閲婃斁浜屽厓淇″彿閲忥纸binary_semaphore_deallocate锛夛纴浣跨敤 semctl 鍑芥暟杩涜屽垹闄ゆ搷浣滐纴纭淇濊祫婧愮殑姝g‘閲婃斁銆



鍒嗛厤浜屽厓淇″彿閲忥细 int binary_semaphore_allocation (key_t key, int sem_flags)锛岃繑锲 semget 镄勭粨鏋滐纴濡傛灉闇瑕佸垯鍒涘缓淇″彿閲忋


閲婃斁浜屽厓淇″彿閲忥细 int binary_semaphore_deallocate (int semid)锛岃皟鐢 semctl 鍑芥暟鍒犻櫎淇″彿閲忥纴鍙傛暟鍖呮嫭淇″彿閲忕粍镙囱瘑绗﹀拰甯搁噺 IPC_RMID銆


镓╁𪾢璧勬枡

Linux 鎻愪緵镄勫悇绉岖郴缁熻皟鐢ㄦ潵瀹炵幇涓涓鍏锋湁涓ょ岖姸镐佺殑淇″彿閲忥纸binary semaphore锛夈

D. c语言实例,linux线程同步的信号量方式 谢谢

这么高的悬赏,实例放后面。信号量(sem),如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。信号量函数的名字都以"sem_"打头。线程使用的基本信号量函数有四个。

信号量初始化。
intsem_init(sem_t*sem,intpshared,unsignedintvalue);
这是对由sem指定的信号量进行初始化,设置好它的共享选项(linux只支持为0,即表示它是当前进程的局部信号量),然后给它一个初始值VALUE。
等待信号量。给信号量减1,然后等待直到信号量的值大于0。
intsem_wait(sem_t*sem);
释放信号量。信号量值加1。并通知其他等待线程。
intsem_post(sem_t*sem);
销毁信号量。我们用完信号量后都它进行清理。归还占有的一切资源。
intsem_destroy(sem_t*sem);
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
#include<errno.h>
#definereturn_if_fail(p)if((p)==0){printf("[%s]:funcerror!/n",__func__);return;}
typedefstruct_PrivInfo
{
sem_ts1;
sem_ts2;
time_tend_time;
}PrivInfo;
staticvoidinfo_init(PrivInfo*thiz);
staticvoidinfo_destroy(PrivInfo*thiz);
staticvoid*pthread_func_1(PrivInfo*thiz);
staticvoid*pthread_func_2(PrivInfo*thiz);
intmain(intargc,char**argv)
{
pthread_tpt_1=0;
pthread_tpt_2=0;
intret=0;
PrivInfo*thiz=NULL;
thiz=(PrivInfo*)malloc(sizeof(PrivInfo));
if(thiz==NULL)
{
printf("[%s]:Failedtomallocpriv./n");
return-1;
}
info_init(thiz);
ret=pthread_create(&pt_1,NULL,(void*)pthread_func_1,thiz);
if(ret!=0)
{
perror("pthread_1_create:");
}
ret=pthread_create(&pt_2,NULL,(void*)pthread_func_2,thiz);
if(ret!=0)
{
perror("pthread_2_create:");
}
pthread_join(pt_1,NULL);
pthread_join(pt_2,NULL);
info_destroy(thiz);
return0;
}
staticvoidinfo_init(PrivInfo*thiz)
{
return_if_fail(thiz!=NULL);
thiz->end_time=time(NULL)+10;
sem_init(&thiz->s1,0,1);
sem_init(&thiz->s2,0,0);
return;
}
staticvoidinfo_destroy(PrivInfo*thiz)
{
return_if_fail(thiz!=NULL);
sem_destroy(&thiz->s1);
sem_destroy(&thiz->s2);
free(thiz);
thiz=NULL;
return;
}
staticvoid*pthread_func_1(PrivInfo*thiz)
{
return_if_fail(thiz!=NULL);
while(time(NULL)<thiz->end_time)
{
sem_wait(&thiz->s2);
printf("pthread1:pthread1getthelock./n");
sem_post(&thiz->s1);
printf("pthread1:pthread1unlock/n");
sleep(1);
}
return;
}
staticvoid*pthread_func_2(PrivInfo*thiz)
{
return_if_fail(thiz!=NULL);
while(time(NULL)<thiz->end_time)
{
sem_wait(&thiz->s1);
printf("pthread2:pthread2gettheunlock./n");
sem_post(&thiz->s2);
printf("pthread2:pthread2unlock./n");
sleep(1);
}
return;
}
阅读全文

与linux信号量的使用相关的资料

热点内容
3j指标源码怎么用 浏览:862
出发命令 浏览:180
比较低碳钢和铸铁在压缩 浏览:319
天眼精准打击指标源码 浏览:938
pythondataframe 浏览:451
单片机的继电器原理图怎么画 浏览:895
自学程序员好考吗 浏览:978
还款解压再质押 浏览:970
doc2pdf 浏览:392
Android提示为空 浏览:623
sql预编译和执行的语法 浏览:111
复盛压缩机选型软件 浏览:746
android培训大纲 浏览:60
docker镜像内编译 浏览:861
缴纳社保app哪个好 浏览:416
哪个app跑步有钱 浏览:58
货币理论pdf 浏览:428
python35键盘输入 浏览:289
安卓手机头部自定义怎么取消 浏览:26
python套利交易 浏览:790