一、信号量:(数据操作锁)控制进程间互斥、同步等,协调多个程序同时访问一个共享资源。

    工作原理:信号量只能有两种操作等待和操作,即:P V操作,必须是原子操作。

              P(sv):如果 sv 的值大于零就减一;如果它的值为零,就挂起;

              V(sv):如果有被挂起的,恢复运行,如果没有就加一。

二、函数原型:

    int semget(key_t key, int nsems,int semflg);

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

    int semctl(int semid, int semnum, int cmd, ...);

    /*    

     *    semid:信号量集的标识符;    semnum:第几个信号量;

     *    cmd:需要执行的命令,根据命令的不同,函数有三个或四个参数(union)

     */

     cmd:IPC_RMID,立即删除信号集,唤醒被阻塞的进程;

     cmd:SETVAL,设置信号量集中的一个单独的信号量的值。

     cmd:GETALL用于读取信号量集中的所有信号量的值。

     union semun

     {

         int val;

         struct semid_ds *buf;

         unsigned short *array;

         struct seminfo *_buf;

      };//用户需自己定义声明

      struct sembuf

      {

          unsigned short sem_num;

          short sem_op;

          short sem_flg;

      };

三、代码实现:

//sem.h

#pragma once#include
#include
#include
#include
#include
#include
#include
#define _PATH_ "."#define _ID_ 0x666static int op_sem(int sem_id, int op, int which);int creat_sem(int _sem_num);int get_sem();int init_sem(int _sem_id, int _which);int sem_p(int _sem_id, int _which);int sem_v(int _sem_id, int _which);int destroy_sem(int _sem_id);union semun{ int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf;};

//sem.c

#include"sem.h"int creat_sem(int snum){	int flags = IPC_CREAT|IPC_EXCL|0666;	key_t key = ftok(_PATH_, _ID_);	if(key < 0)	{		perror("ftok");		return -1;	}	return semget(key, snum, flags);}int get_sem(){	key_t key = ftok(_PATH_, _ID_);	if(key < 0)	{		perror("ftok");		return -1;	}	return semget(key, 0, IPC_CREAT);}static int op_sem(int sem_id, int op, int which){	struct sembuf sem;	memset(&sem, '\0',sizeof(sem));	sem.sem_num = which;	sem.sem_op = op;	sem.sem_flg = 0;	if(semop(sem_id, &sem, 1) < 0)	{		perror("semop");		return -1;	}	return 0;}int sem_p(int sem_id, int which){	return op_sem(sem_id, -1, which);}int sem_v(int sem_id, int which){	return op_sem(sem_id, 1, which);}int init_sem(int sem_id, int which){	union semun _semun;	_semun.val = 1;	if(semctl(sem_id, SETVAL, which, _semun) < 0)	{		perror("semctl");		return -1;	}	return 0;}int destroy_sem(int sem_id){	if(semctl(sem_id, 0, IPC_RMID, NULL) < 0)	{		perror("semctl");		return -1;	}	return 0;}

//test.c

#include"sem.h"int main(){	int sem_id = creat_sem(1);	if(sem_id < 0)	{		printf("creat_sem error");		return -1;	}	init_sem(sem_id, 0);	pid_t id  = fork();	if(id < 0)	{		perror("fork");		return -1;	}	else if(id == 0)	{		int sem_id = get_sem(1);		while(1)		{			sem_p(sem_id, 0);				printf("A");			sleep(1);			fflush(stdout);			printf("A");			sleep(2);			fflush(stdout);			sem_v(sem_id, 0);		}	}	else	{		while(1)		{			sem_p(sem_id, 0);				printf("B");			fflush(stdout);			printf("B");			sleep(1);			fflush(stdout);			sem_v(sem_id, 0);		}		waitpid(id, NULL, 0);		destroy_sem(sem_id);	}	return 0;}

四、实现结果:

使用信号量之前

使用信号量之后