简易广州网站建设,盘锦市城乡建设厅网站,网站网络广告如何建设,做ios试玩推广网站1.认识信号量 方便理解#xff1a;信号量就是一个计数器。当它大于0能用#xff0c;小于等于0#xff0c;用不了#xff0c;这个值自己给。 
2.特点#xff1a; 
信号量用于进程间同步#xff0c;若要在进程间传递数据需要结合共享内存。信号量基于操作系统的 PV 操作信号量就是一个计数器。当它大于0能用小于等于0用不了这个值自己给。 
2.特点 
信号量用于进程间同步若要在进程间传递数据需要结合共享内存。信号量基于操作系统的 PV 操作程序对信号量的操作都是原子操作。P操作:拿锁。V操作放回锁每次对信号量的 PV 操作不仅限于对信号量值加 1 或 减1 而且可以加加减任意正整数。支持信号量组 
3.有关api 
#include sys/sem.h//1.创建或获取一个信号量组若成功返回信号量级ID失败返回-1
int semget(key_t key, int num_sems, int sem_flags);//2.对信号量组进行操作改变信号量的值成功返回0失败返回-1
int semop(int semid, struct sembuf semoparray[], size_t numops);//3.控制信号量的相关信息
int semctl(int semid, int sem_num, int cmd, ...); 
1.semget 
功能创建一个新的信号量或获取一个已经存在的信号量的键值。 
返回值成功返回信号量的标识码ID。失败返回-1 
参数 
key  为整型值用户可以自己设定。有两种情况 
1.       键值是IPC_PRIVATE该值通常为0意思就是创建一个仅能被进程进程给我的信号量。 
2.       键值不是IPC_PRIVATE我们可以指定键值例如1234也可以一个ftok()函数来取得一个唯一的键值。 
sems 表示初始化信号量的个数。比如我们要创建一个信号量则该值为1.,创建2个就是2。 
flags  信号量的创建方式或权限。有IPC_CREATIPC_EXCL。 
IPC_CREAT如果信号量不存在则创建一个信号量否则获取。 
IPC_EXCL只有信号量不存在的时候新的信号量才建立否则就产生错误。 2.semop 
//2.对信号量组进行操作改变信号量的值成功返回0失败返回-1
int semop(int semid, struct sembuf semoparray[], size_t numops); 
该函数的主要作用是执行对一个或多个信号量的原子操作包括P操作sem减1和V操作sem加1以实现进程间的同步与互斥。 
其中参数semid为信号量集的标识符参数sops指向进行操作的结构体数组的首地址参数nsops指出将要进行操作的信号的个数。 
需要注意的是信号量的值只能通过PV操作来改变。当信号量的值大于0时表示当前有可用资源进程可以继续执行若信号量的值小于等于0则表示无可用资源进程需要暂停等待。 
另外semop函数调用成功返回0失败返回-1。因此在使用该函数时需要进行错误检查以确保操作的正确性。 
具体参数解释 _semid : 信号量的标识码。也就是semget的返回值。 _sembuf是一个指向结构体数组的指针。 
1 struct sembuf 
2 {
3     short sem_num; // 信号量组中对应的序号0sem_nums-1
4     short sem_op;  // 信号量值在一次操作中的改变量
5     short sem_flg; // IPC_NOWAIT, SEM_UNDO
6 }sembuf解释 
1.em_num:  操作信号在信号集中的编号。第一个信号的编号为0 
2.sem_op : 如果其值为正数该值会加到现有的信号内含值中。通常用于释放所控资源的使用权如果sem_op的值为负数而其绝对值又大于信号的现值操作将会阻塞直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用权如果sem_op的值为0则操作将暂时阻塞直到信号的值变为0。 
3.semflg 
IPC_NOWAIT //对信号的操作不能满足时semop()不会阻塞并立即返回同时设定错误信息。 
IPC_UNDO //程序结束时(不论正常或不正常)保证信号值会被重设为semop()调用前的值。这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁造成该资源永远锁定。 _nsops操作结构的数量恒大于或等于1。 
//3.控制信号量的相关信息
int semctl(int semid, int sem_num, int cmd, ...); 
3.semctl 
semid表示要操作的信号量集的标识符通常由 semget() 函数返回。semnum表示要操作的信号量的索引号这里设置为 0表示对第一个信号量进行操作。 cmd    命令表示要进行的操作  下面列出的这些命令来源于百度 参数cmd中可以使用的命令如下 IPC_STAT读取一个信号量集的数据结构semid_ds并将其存储在semun中的buf参数中。        IPC_SET设置信号量集的数据结构semid_ds中的元素ipc_perm其值取自semun中的buf参数。        IPC_RMID将信号量集从内存中删除。        GETALL用于读取信号量集中的所有信号量的值。        GETNCNT返回正在等待资源的进程数目。        GETPID返回最后一个执行semop操作的进程的PID。        GETVAL返回信号量集中的一个单个的信号量的值。        GETZCNT返回这在等待完全空闲的资源的进程数目。        SETALL设置信号量集中的所有的信号量的值。        SETVAL设置信号量集中的一个单独的信号量的值。 通常为标黄的命令 
如果有第四个参数它通常是一个union semum结构定义如下 
union semun {int val;          // 用于SETVAL命令表示要设置的信号量的值。struct semid_ds *buf; // 用于IPC_STAT、IPC_SET命令指向一个semid_ds结构体的指针。unsigned short *array; // 用于GETALL、SETALL命令指向一个无符号短整型数组的指针。struct seminfo *__buf; // 用于IPC_INFO命令指向一个seminfo结构体的指针Linux-specific。
};前两个参数与前面一个函数中的一样command通常是下面两个值中的其中一个 SETVAL用来把信号量初始化为一个已知的值。这个值通过union semun中的val成员设置其作用是在信号量第一次使用前对它进行设置。 
IPC_RMID用于删除一个已经无需继续使用的信号量标识符。 4.代码例子 
使用信号量实现父子进程先后进行。 
#include stdio.h
#include sys/types.h
#include sys/ipc.h
#include sys/sem.h
#include stdlib.h/*
//1.创建或获取一个信号量组若成功返回信号量级ID失败返回-1
int semget(key_t key, int num_sems, int sem_flags);//2.对信号量组进行操作改变信号量的值成功返回0失败返回-1
int semop(int semid, struct sembuf semoparray[], size_t numops);//3.控制信号量的相关信息
int semctl(int semid, int sem_num, int cmd, ...);*/// union for semctl to initialize
union semun {int val;          // 用于SETVAL命令表示要设置的信号量的值。struct semid_ds *buf; // 用于IPC_STAT、IPC_SET命令指向一个semid_ds结构体的指针。unsigned short *array; // 用于GETALL、SETALL命令指向一个无符号短整型数组的指针。struct seminfo *__buf; // 用于IPC_INFO命令指向一个seminfo结构体的指针Linux-specific。
};//initialize sem to 0int init_sem(int sem_id,int value){union semun tmp;tmp.val  value;if(semctl(sem_id,0,SETVAL,tmp)-1){perror(init sem erro);return -1;}return 0;
}//p operate
// if sem  1,get message to sem -1
//if sem  0, process waitint sem_p(int sem_id){struct sembuf pbuf;pbuf.sem_num   0;pbuf.sem_op    -1;pbuf.sem_flg   SEM_UNDO;if(semop(sem_id,pbuf,1)  -1){perror(p operate error);return -1;}return 0;
}//v operate
//sem 1 operateint sem_v(int sem_id){struct sembuf vbuf;vbuf.sem_num   0;vbuf.sem_op    1;//v operatevbuf.sem_flg   SEM_UNDO;if(semop(sem_id,vbuf,1)  -1){perror(v operate error);return -1;}return 0;
}//delete semint del_sem(int sem_id){union semun tmp;if(semctl(sem_id,0,IPC_RMID)  -1){perror(delete sem error);return -1;}return 0;
}int main()
{int  sem_id;key_t key;pid_t pid;//get key numif((key  ftok(.,11))0){perror(semget error);exit(-1);}//build sem only 1if(sem_id  semget(key,1,IPC_CREAT|0700)-1){perror(semget error);exit(-1);}//initilizeinit_sem(sem_id,0);//fatherchild processif((pid  fork()) -1){perror(fork errror);exit(-1);}else if(pid  0){   //child processsleep(1);printf(process from child pid :%d\n,getpid());sem_v(sem_id);//release resource put tne lock}else {  //father processsem_p(sem_id);printf(father process pid:%d\n,getpid());sem_v(sem_id);del_sem(sem_id);}return 0;
}突然意识到结构体和联合体是不同的请看文章