进程间通信(二)----信号量

信号量,本质是一个计数器,这个计数器用来描述临界资源的数目;

原子性,要么读()完,要么不读()

信号量既是用来解决进城同步与互斥问题的机制,也可以实现进程间通信;

临界资源:不同进程能够看到的同一份资源;

临界区:双方访问临界资源的那份代码(readwrite);

通过保护临界区来保护临界资源;

互斥:任何时刻只有一个进程原子性的访问临界资源;

饥饿:长时间未得到某种资源;

同步:大部分在互斥的前提下,以某种顺序依次访问临界资源;

p操作:-1(信号量sem的值减1sem=sem-1),如果sem>0该进程继续执行,否则该进程置为等待状态,排入等待队列;

v操作:+1(信号量sem的值加1sem=sem+1),如果sem>0该进程继续执行,否则释放队列中第一个等待信号量的进程。

信号量要被不同的进程看到,其本身就是临界资源,信号量的操作包括创建,初始化,获取,释放

信号量的两种状态:二元信号量(表示资源只有一个,本身可以提供互斥机制),多元信号量

comm.h

#ifndef _COMM_H_
#define _COMM_H_
#define PATHNAME "."
#define PROJ_ID 0666
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<unistd.h>
typedef 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 */
	void *__pad;
}mysemun;
int create_sems(int nums);
int get_sems();
int destory_sems(int semid);
int init_sems(int semid,int which,int _val);
int P(int semid,int which);
int V(int semid,int which);
int comm_sems(int nums,int flags);
int comm_semop(int semid,int which,int op);
#endif
comm.c

#include"comm.h"
int comm_sems(int nums,int flags)
{
   key_t key=ftok(PATHNAME,PROJ_ID);
   int semid=semget(key,nums,flags);
   if(semid<0)
   {
     perror("semget");
	 return -1;
   }
   return semid;
}
int create_sems(int nums)
{
  return comm_sems(nums,IPC_CREAT | IPC_EXCL | 0666);
}
int get_sems()
{
  return comm_sems(0,IPC_CREAT);
}
int init_sems(int semid,int which,int _val)
{
 mysemun un;
 un.val=_val;
 if(semctl(semid,which,SETVAL,un)<0)
 {
   perror("semctl");
   return -1;
 }
 return 0;
}
int destory_sems(int semid)
{
 if(semctl(semid,0,IPC_RMID)<0)
 {
   perror("semctl");
   return -1;
 }
 return 0;
}
int comm_semop(int semid,int which,int op)
{
  struct sembuf sbuf;
  sbuf.sem_num=0;
  sbuf.sem_op=op;
  sbuf.sem_flg=SEM_UNDO;
  if(semop(semid,&sbuf,1)<0)
  {
    perror("semop");
	return -1;
  }
  return 0;
}
int P(int semid,int which)
{
  return comm_semop(semid,which,-1);
}
int V(int semid,int which)
{
  return comm_semop(semid,which,1);
}

sems.c

#include"comm.h"
int main()
{
  int semid=create_sems(1);
  init_sems(semid,0,1);
  pid_t pid=fork();
  if(pid<0)
  {
    perror("fork");
	return -1;
  }
  else if(pid==0)
  {
    //child
	get_sems();
	while(1)
	{
	  P(semid,0);
	  printf("A");
	  usleep(12345);
	  fflush(stdout);
	  printf("A");
	  usleep(22345);
	  fflush(stdout);
	  V(semid,0);
	}
  }
	else
	{
		//father
	  while(1)
	  {
	   P(semid,0);
	   printf("B");
	   fflush(stdout);
	   usleep(12345);
	   printf("B");
	   usleep(22345);
	   fflush(stdout);
	   V(semid,0);
	  }
	  waitpid(NULL);
	  destory_sems(semid);
	}
  return 0;  
}

Makefile
sems:comm.c sems.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f sems


使用PV操作之前


使用PV操作之后


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值