linux sem 多进程sem_open sem_init,信号灯-布布扣-bubuko.com

本文详细介绍了Linux系统中信号灯的概念,包括有名信号灯和基于内存的信号灯,以及它们的区别。重点讲解了有名信号灯的创建、关闭、删除等操作,如sem_open、sem_close、sem_unlink等函数的使用,并提供了同步多线程和多进程的示例代码。同时,还阐述了基于内存的信号灯如何通过sem_init和sem_destroy进行同步。信号灯在多线程和多进程同步中起到关键作用,通过调整信号灯的值实现对共享资源的访问控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念:

信号灯用来实现同步——用于多线程,多进程之间同步共享资源(临界资源)。信号灯分两种,一种是有名信号灯,一种是基于内存的信号灯。

有名信号灯,是根据外部名字标识,通常指代文件系统中的某个文件。

基于内存的信号灯,它主要是把信号灯放入内存的,基于内存的信号灯,同步多线程时,可以放到该多线程所属进程空间里;如果是同步多进程,那就需要把信号灯放入到共享内存中(方便多个进程访问)。

有名信号灯和基于内存的信号灯,具体区别体现在创建和销毁两个函数。有名信号灯使用sem_open和sem_close函数。基于内存的信号灯使用sem_init和sem_destroy函数。sem_init的参数可以控制是同步多线程,还是多进程;且该函数只能调用1次,因为调用后信号灯就存在了( 内存指针存在)。一般,使用基于内存的信号灯同步同进程多线程,使用有名信号灯同步多进程。

有名信号灯同步多线程:

1.sem_open函数。

功能:创建并初始化信号灯,如果存在就返回存在的信号灯。

头文件:#include函数原型:sem_t* sem_open(const char * name,int oflag,mode_t mode,unsigned intvalue);

或者:sem_t* sem_open(const char * name,intoflag);

参数:name是给信号灯指定一个名字。oflag的值为O_CREAT,表示如果信号灯不存在,创建信号灯;为O_CREAT|O_EXCL,如果信号灯不存在报错。后面两个参数,只有新建信号灯时使用。mode为信号灯的权限(0644),value为信号灯的值。

返回值:成功时,返回信号灯的指针,错误返回SEM_FAILED2.sem_close函数。

功能:关闭引用信号灯,信号灯引用计数减1。

头文件:#include函数原型:int sem_close(sem_t *sem)

参数:sem为信号灯的指针

返回值:成功时,返回0,失败,-1注:每个信号灯有一个引用计数器记录当前打开次数.关闭一个信号灯并没有将它从系统中删除,而是信号灯引用计数减13.sem_unlink函数

功能:信号灯引用计数为0时,从系统中删除信号灯。

头文件:#include函数原型:int sem_close(const char *name)

参数:name为信号灯的外部名字

返回值:成功时,返回0,失败,-1

4.sem_wait/sem_trywait函数

功能:等待共享资源,信号灯值为0就睡眠,信号灯值大于0,就使用共享资源,信号灯值减1。sem_trywait当信号灯值为0时,不睡眠,报错。

头文件:#include函数原型:int sem_wait(sem_t *sem),int sem_trywait(sem_t *sem)

参数:sem为信号灯指针

返回值:成功时,返回0,失败,-1

5.sem_getvalue函数

功能:获得信号灯的值

头文件:#include函数原型:int sem_getvalue(sem_t *sem,int *valp)

参数:sem为信号灯指针,valp为信号灯的值

返回值:成功时,返回0,失败,-1

6.sem_post函数

功能:使用完共享资源后,信号灯值加1,唤醒其他睡眠的。

头文件:#include函数原型:int sem_post(sem_t *sem)

参数:sem为信号灯指针

返回值:成功时,返回0,失败,-1

总结:

sem_wait在一个信号灯上等待(以锁住一个资源或等待一个时间),如果信号灯计数比0大,sem_wait函数将计数器减一并马上返回,否则,线程阻塞,一个阻塞的线程通过sem_post来发布一个信号灯(开锁一个资源或等待一个线程),

如果一个以上的线程在信号灯上等待,sem_post将唤醒其中一个(优先级最高的或最早等待的线程),如果没有线程在等待,信号灯计数器被加一。

假如有个代码段,期望最多有两个线程同时在里面执行(其他线程必须等待),可以使用一个信号灯而不需要附加任何状态,初始化信号灯值为2,然后再代码段开始调用sem_wait,结尾处调用sem_post,然后两个线程可以再信号登上等待而不被阻塞,

但是第三个线程将发现信号灯计数器为0,并且阻塞,每个系那成退出代码区时,他信号灯释放一个等待吸纳城(如果有的话恢复计数器)。

有名信号灯同步多进程:

unix网络编程第二卷,如是说不同进程(不管是否彼此有无亲缘关系),他们都可以访问同一个信号灯,只是需要在sem_open的时候传入的名字是一样就行。在有亲缘关系时,Posix中的fork如是描述,在父进程中打开的任何信号灯,仍应在子进程中打开。

示例代码:

/*semopen_pro.c*/#include#include#include#include#include#include

voidprint();

sem_t*sem;int main(int argc,char *argv[])

{int n=0,j;

pid_t pid;if(argc != 2)

{

printf("Usage:%s name.\n",argv[0]);

exit(0);

}//该信号灯不会因为不同进程而不同。

sem=sem_open(argv[1],O_CREAT,0644,3);while(n++<5)

{

pid=fork();if(pid == 0)

{

sem_wait(sem);

print();

sleep(1);

sem_post(sem);

printf("finish,the pid is %d\n",getpid());

exit(0);

}

}

j=0;//等待所有子进程退出

while(j++<5)

wait(NULL);

sem_close(sem);

sem_unlink(argv[1]);return 0;

}voidprint()

{intvalue;

printf("pid is %d, get the resource\n",getpid());

sem_getvalue(sem,&value);

printf("now,the semaphore value is %d\n",value);

}

[email protected]:/mnt/hgfs/C_libary# gcc -o semopen_pro semopen_pro.c

semopen_pro.c: In function ‘main’:

semopen_pro.c:19: warning: incompatible implicit declaration of built-infunction ‘exit’

semopen_pro.c:34: warning: incompatible implicit declaration of built-infunction ‘exit’/tmp/ccUECdL7.o: In function `main‘:

semopen_pro.c:(.text+0x5d): undefined reference to `sem_open‘semopen_pro.c:(.text+0x81): undefined reference to `sem_wait‘semopen_pro.c:(.text+0x9f): undefined reference to `sem_post‘semopen_pro.c:(.text+0x107): undefined reference to `sem_close‘semopen_pro.c:(.text+0x117): undefined reference to `sem_unlink‘/tmp/ccUECdL7.o: In function `print‘:

semopen_pro.c:(.text+0x14e): undefined reference to `sem_getvalue‘collect2: ld returned 1exit status

注:sem_XXX函数不是标准库函数,链接时需要指定库-lrt or -o semopen_pro semopen_pro.c

semopen_pro.c: In function ‘main’:

semopen_pro.c:19: warning: incompatible implicit declaration of built-infunction ‘exit’

semopen_pro.c:34: warning: incompatible implicit declaration of built-insemopen_pro sem

pidis 5262, getthe resource

now,the semaphore valueis 2pidis 5263, getthe resource

now,the semaphore valueis 1pidis 5264, getthe resource

now,the semaphore valueis 0finish,the pidis 5262pidis 5265, getthe resource

now,the semaphore valueis 0finish,the pidis 5263pidis 5266, getthe resource

now,the semaphore valueis 0finish,the pidis 5264finish,the pidis 5265finish,the pidis 5266

基于内存的信号灯同步多线程:

sem_init()

功能:初始化信号灯。

头文件:#include函数原型:int sem_open(sem_t * sem,int shared,unsigned intvalue);

参数:sem为信号灯指针,shared是指同步多线程还是多进程(0:多线程,其他:多进程),value为信号量值

返回值:成功时,返回0,失败时,返回-1sem_destroy()

功能:关闭信号

头文件:#include函数原型:int sem_destroy(sem_t *sem)

参数:sem为信号灯的指针

返回值:成功时,返回0,失败,-1

/*seminit_pth*/#include#include#include#include

voidprint();void * thread_function(void *arg);

sem_t sem;int main(int argc,char *argv[])

{int n=0;

pthread_t tid;//init semaphore

sem_init(&sem,0,3);while(n++<5)

{if((pthread_create(&tid,NULL,thread_function,NULL))!=0)

{

printf("can‘t create pthread.\n");

exit(0);

}

}

pthread_join(tid,NULL);

sem_destroy(&sem);return 0;

}void * thread_function(void *arg)

{

sem_wait(&sem);

print();

sleep(1); // sem_post(&sem);

printf("finish, pthread_id is %d\n",pthread_self());

}voidprint()

{intvalue;

printf("pthread_id is %d, get the resource\n",pthread_self());

sem_getvalue(&sem,&value);

printf("now,the semaphore value is %d\n",value);

}

[email protected]:/mnt/hgfs/C_libary# gcc -lrt -o seminit_pth seminit_pth.c

seminit_pth.c: In function ‘main’:

seminit_pth.c:21: warning: incompatible implicit declaration of built-infunction ‘exit’

seminit_pth.c: In function ‘thread_function’:

seminit_pth.c:35: warning: format ‘%d’ expects type ‘int’, but argument 2has type ‘pthread_t’

seminit_pth.c: In function ‘print’:

seminit_pth.c:41: warning: format ‘%d’ expects type ‘int’, but argument 2has type ‘pthread_t’

[email protected]:/mnt/hgfs/seminit_pth

pthread_idis -1224959120, getthe resource

now,the semaphore valueis 2pthread_idis -1233351824, getthe resource

now,the semaphore valueis 1pthread_idis -1241744528, getthe resource

now,the semaphore valueis 0finish, pthread_idis -1224959120finish, pthread_idis -1233351824finish, pthread_idis -1241744528pthread_idis -1250137232, getthe resource

now,the semaphore valueis 2pthread_idis -1216566416, getthe resource

now,the semaphore valueis 1finish, pthread_idis -1250137232finish, pthread_idis -1216566416

原文:https://www.cnblogs.com/tianzeng/p/9314463.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值