信号量实现

信号量实现

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>


//       int semop(int semid, struct sembuf *sops, unsigned nsops);

union semun {
        int              val;    /* Value for SETVAL */
        struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
        unsigned short  *array;  /* Array for GETALL, SETALL */
        struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */
};
void pGetKey(int id)
{
        struct sembuf set;
        set.sem_num = 0;
        set.sem_op = -1;
        set.sem_flg = SEM_UNDO;
        semop(id,&set,1);
        printf("get key\n");
}
void vPutBackKey(int id)
{
        struct sembuf set;
        set.sem_num = 0;
        set.sem_op = 1;
        set.sem_flg = SEM_UNDO;
        semop(id,&set,1);
        printf("put back the key\n");
}
int main(int argc,char const *argv[])
{
		//1.获取或创建信号量
		//int semget(key_t key, int nsems, int semflg);
		//_nsems 表示初始化信号量的个数。比如我们要创建一个信号量,则该值为1.,创建2个就是2。
		/*semflg  :信号量的创建方式或权限。有IPC_CREAT,IPC_EXCL。
		  IPC_CREAT如果信号量不存在,则创建一个信号量,否则获取。
          IPC_EXCL只有信号量不存在的时候,新的信号量才建立,否则就产生错误。*/
        int semid;//创建或获取信号量返回的信号量ID值,成功返回信号量的标识码ID。失败返回-1;
        key_t key;
        key = ftok(".",2);//调用ftok函数,系统随机生成一个唯一的key,也可以手工输入一个key值,如0x1234
        semid = semget(key,1,IPC_CREAT|0666);//1:信号量集合中有1个信号量;0666表示权限
        //2.初始化信号量
        //int semctl(int semid, int semnum, int cmd, ...);
        /* semctl  功能:对信号量进行控制
			参数:semid, 信号量标识符
			sem_num, 信号量组中的编号,从0开始,如果只有一个信号量,则取0
			cmd, SETVAL 把信号量初始化为指定的值,具体的值由第4个参数确定
			注意:只能对信号量初始化一次,如果在各进程中,分别对该信号量进行初始化,则可能导致错误!
           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   设置信号量集中的一个单独的信号量的值。
		此函数有三个或四个参数,具体取决于cmd。当有四个时,第四个具有类型union semun。调用程序必须按man中方式定义此并集:
		参数4, 类型为:
		union semun {
               int              val; // SETVAL命令要设置的值  
               struct semid_ds *buf;    
               unsigned short  *array;  
               struct seminfo  *__buf;  
           };
           注意:union semun类型要求自己定义,有些Linux发行版在sys/sem.h中定义,有些发行版则没有定义。*/
        union semun initsem;//定义一个第四个参数,联合体
        initsem.val = 0;
        semctl(semid,0,SETVAL,initsem);//初始化信号量,0:操作第0个信号量,SETVAL:表示需要设置的是信号量的值,其值设置为initsem
        int pid = fork();
        if(pid > 0){
                pGetKey(semid);//去拿锁
                printf("this is father\n");
                vPutBackKey(semid);//锁放回去
                semctl(semid,0,IPC_RMID);//销毁锁
        }else if(pid == 0){
                printf("this is child\n");
                vPutBackKey(semid);
        }else{
                printf("fork error\n");
        }
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值