信号量(也叫信号灯)是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语(不会被其他指令中断)。信号量是进程/线程同步的一种方式,有时候我们需要保护一段代码,使它每次只能被一个执行进程/线程运行,这种工作就需要一个二进制开关;有时候需要限制一段代码可以被多少个进程/线程执行,这就需要用到关于计数信号量。信号量开关是二进制信号量的一种逻辑扩展,两者实际调用的函数都是一样。
信号量分为以下三种:
1、System V信号量,在内核中维护,可用于进程或线程间的同步,常用于进程的同步。
2、Posix有名信号量,一种来源于POSIX技术规范的实时扩展方案(POSIX Realtime Extension),可用于进程或线程间的同步,常用于线程。
3、Posix基于内存的信号量,存放在共享内存区中,可用于进程或线程间的同步。
为了获得共享资源进程需要执行下列操作:
(1)测试控制该资源的信号量。
(2)若信号量的值为正,则进程可以使用该资源。进程信号量值减1,表示它使用了一个资源单位。此进程使用完共享资源后对应的信号量会加1。以便其他进程使用。
(3)若信号量的值为0,则进程进入休息状态,直至信号量值大于0。进程被唤醒,返回第(1)步。
为了正确地实现信号量,信号量值的测试值的测试及减1操作应当是原子操作(原子操作是不可分割的,在执行完毕前不会被任何其它任务或事件中断)。为此信号量通常是在内核中实现的。
System V IPC机制:信号量。
函数原型:
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/types.h>
int semget(key_t key,int nsems,int flag);
int semop(int semid,struct sembuf *sops,size_t num_sops);
int semctl(int semid, int semnum, int cmd, …);
一、示例:程序被打断出错
//创建、初始化共享内存
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <sys/shm.h>
#define PROJ_ID 1
#define TIMES 1000000
int main(int argc,char* argv[])
{
if(argc!=2)
{
printf("error args\n");
return -1;
}
key_t skey;
skey=ftok(argv[1],PROJ_ID);
if(-1==skey)
{
perror("ftok");
return -1;
}
printf("the key is %d\n",skey);
int shmid;
shmid=shmget(skey,1<<12,0600|IPC_CREAT);//创建共享内存
if(-1==shmid)
{
perror("shmget");
return -1;
}
printf("the shmid is %d\n",shmid);
int* p;
p=shmat(shmid,NULL,0);
if((int*)-1==p)
{
perror("shmat");
return -1;
}
*p=0;//初始化共享内存
return 0;
}
//add1.c&&add2.c分别将内存中的数加10000000次1
#include <stdio.h>
#include <sys/types.h>
#include <s