用来管理对资源的访问
一个特殊的变量,只允许对它进行等待(wait)和发送信号(signal),代表可用资源个数,
取0,1 二值信号量
取 3,5 计数信号量
p操作:原子减一,代表获取资源,可能阻塞
v操作:原子加一 代表释放资源,不会阻塞
临界区:真正执行数据更新的代码需要独占式地执行(即临界资源所在位置)
临界资源:只有一个进程可以进入这个临界代码并拥有对资源独占式的访问权(同一时刻只能执行一个代码)
#include
作用:创建一个新信号量或取得一个已有信号量的键;
定义:int semget(key_t key,int num_sems,int sem_flags);
key:整数值,不相关的进程可以通过它访问同一个信号量。
num_sems:参数指定需要的信号量数目,他几乎总是取值为1.
sem_flag:类似于文件的访问权限,一般用IPC_CREAT:创建一个新信号量,即使给出的键是一个已有信号量的键,也不会产生错误。一般还要用到IPC_EXCL:确保创建出一个新的唯一的信号量,如果信号量已存在,将返回错误。
这个函数在成功时返回一个整数,即其他信号量函数将用到的信号量标识符。
如果失败返回-1。
作用:semop()对信号量进行改变,做 P 操作或者 V 操作
头文件 sem.h
- #include
- #include
- #include
- #include
- #include
- #include
- union semun{
- int val;
- };
- void sem_init();
- void sem_p();
- void sem_v();
- void sem_destroy();
- #include "sem.h"
- static int semid=-1;
- void sem_init()
- {
- semid=semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);//创建一个新的信号量
- if(semid==-1){
- semid=semget((key_t)1234,1,0600);//表明这个信号量是已存在的信号量
- if(semid==-1)
- {
- printf("semget err\n");//这个信号量创建失败
- }
- }
- else{
- union semun a;
- a.val=1;
- if(semctl(semid,0,SETVAL,a)==-1)//初始化该信号量
- {
- printf("semctl err\n");
- }
- }
- }
- void sem_p()
- {
- struct sembuf sem;
- sem.sem_flg=SEM_UNDO;
- sem.sem_num=0;
- sem.sem_op=-1;//p操作
- if(semop(semid,&sem,1)==-1){
- printf("sem_p err\n");
- }
- }
- void sem_v()
- {
- struct sembuf sem;
- sem.sem_flg=SEM_UNDO;
- sem.sem_num=0;
- sem.sem_op=1;//v操作
- if(semop(semid,&sem,1)==-1){
- printf("sem_v err\n");
- }
- }
- void sem_destroy()
- {
- if(semctl(semid,0,IPC_RMID)==-1)//删除该信号量
- {
- printf("sem_destory err\n");
- }
- }
定义一个信号量初始化值为1 ,当a进程拿到这个信号量,就进行p操作,让这个信号量为0,此时b进程没有可以使用的信号量就会等待a进程结束,a进程结束后会v操作,让信号量为1 ,此时b进程就可以执行,依次循环下去。
a.c
- #include"sem.h"
- int main()
- {
- sem_init();//
- for(int i = 0; i < 5; i++)
- {
- //p
- sem_p();
- printf("a");
- fflush(stdout);
- int n = rand() % 3;
- sleep(n);
- printf("a");
- fflush(stdout);
- sem_v();
-
- n = rand() % 3;
- sleep(n);
- }
-
- sem_destroy();
- return 0;
- }
b,c
- #include"sem.h"
- int main()
- {
- sem_init();//
- for(int i = 0; i < 5; i++)
- {
- //p
- sem_p();
- printf("b");
- fflush(stdout);
- int n = rand() % 3;
- sleep(n);
- printf("b");
- fflush(stdout);
- sem_v();
-
- n = rand() % 3;
- sleep(n);
- }
- return 0;
- }
此时a和b各是成对出现
shmget()成功返回共享内存的 ID, 失败返回-1
step 3:代码实现
main.c
- #include
- #include
- #include
- #include
- #include
- #include "sem.h"
-
- int main()
- {
- int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);
- if ( shmid == -1 )
- {
- printf("shmget err\n");
- exit(1);
- }
-
- char* s = (char*)shmat(shmid,NULL,0);
- if ( s == (char*)-1)
- {
- printf("shmat err\n");
- exit(1);
- }
-
- sem_init();
- while( 1 )
- {
- printf("input\n");
- char buff[128] = {0};
- fgets(buff,128,stdin);
-
- sem_p(SEM1);
- strcpy(s,buff);
- sem_v(SEM2);
-
- if ( strncmp(buff,"end",3) == 0)
- {
- break;
- }
- }
-
- shmdt(s);
- }
test.c
- #include
- #include
- #include
- #include
- #include
- #include "sem.h"
-
- int main()
- {
- int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);
- if ( shmid == -1 )
- {
- printf("shmget err\n");
- exit(1);
- }
-
- char * s = (char*)shmat(shmid,NULL,0);
- if ( s == (char*)-1)
- {
- printf("shmat err\n");
- exit(1);
- }
-
- sem_init();
- while( 1 )
- {
- sem_p(SEM2);
- if ( strncmp(s,"end",3) == 0 )
- {
- break;
- }
-
- printf("read:%s\n",s);
- sem_v(SEM1);
- }
-
- shmdt(s);
- shmctl(shmid,IPC_RMID,NULL);
- sem_destroy();
- }