Linux进程间通信之信号量

Linux进程间通信之信号量

一.信号量
定义信号变量; sem_t sem1 sem2
初始化信号量
P操作
V操作

功能 信号量(POSOX) 信号量灯(IPC)
定义信号变量 sem_t sem1 semget
初始化信号量 sem_init semctl
P操作 sem_wait semop
V操作 sem_post semop

前面学的信号量时针对的是单个的信号。而信号灯集是一个整体的概念是针对的多个信号量来操作的。

信号灯:
信号灯集合(可以包含多个信号灯) IPC对象是一个信号灯集(多个信号量)
在这里插入图片描述
1.semget
int semget(key_t key, int nsems, int semflg);
所需头文件 #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
函数原型 int semget(key_t key, int nsems, int semflg);
函数参数 key:和信号灯集关联的key值
nsems: 信号灯集中包含的信号灯数目
semflg:信号灯集的访问权限
函数返回值
成功:信号灯集ID
出错:-1
2.semop
所需头文件 #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
函数原型 int semop ( int semid, struct sembuf *opsptr, size_t nops);
函数参数 semid:信号灯集ID
struct sembuf {
short sem_num; // 要操作的信号灯的编号
short sem_op; // 0 : 等待,直到信号灯的值变成0
// 1 : 释放资源,V操作
// -1 : 分配资源,P操作
short sem_flg; // 0(阻塞), IPC_NOWAIT, SEM_UNDO
};
nops: 要操作的信号灯的个数

函数返回值
成功:0
出错:-1
3.semctl
所需头文件 #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
函数原型 int semctl ( int semid, int semnum, int cmd,…union semun arg(不是地址));
函数参数 semid:信号灯集ID
semnum: 要修改的信号灯编号
cmd: GETVAL:获取信号灯的值
SETVAL:设置信号灯的值
IPC_RMID:从系统中删除信号灯集合

函数返回值
成功:0
出错:-1

semctl:cmd:
GETVAL:获取信号灯的值
SETVAL:设置信号灯的值
IPC_RMID:从系统中删除信号灯集合
msgctl:cmd IPC_STAT (获取对象属性)
shmctl:cmd IPC_SET (设置对象属性)

#include "sys/types.h"
#include "sys/sem.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
  int semid;
  semid=semget(IPC_PRIVATE,3,0777);
  if(semid <0)
  {
	printf("creat semaphore failure\n");
	return -1;
  }
  printf("creat semaphore   sucess semid=%d\n",semid);
  system("ipcs -s");
  //while(1);
  // delete semaphore
  semctl(semid,0,IPC_RMID,NULL);
  system("ipcs -s");
  return 0;
}

在这里插入图片描述
SETVAL:设置信号灯的值 信号灯的初始化,类似sem_init;

union semun
 {
	 int val;   
	 //SETVAL:设置信号灯的值
	 struct semid_ds *buf;
	 // IPC_STAT  (获取对象属性)
	 //IPC_SET (设置对象属性)
     unsigned short  *array;  /* Array for GETALL, SETALL */
     struct seminfo  *__buf;  /* Buffer for IPC_INFO (Linux-specific) */
   };

通过POSOX实现同步信号:
PV操作

#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
#include "semaphore.h"
#include <unistd.h>
sem_t sem;
void *fun(void *var)//child thread code
{
  int j;
  //p  wait
  sem_wait(&sem);  //sleep
  for(j=0;j<10;j++)//second
  {
    usleep(100);
	printf("this is fun j=%d\n",j);
  }
}
int main()//main thread code
{
  int i;
  char str[]="hello linux\n";
  pthread_t tid;
  int ret;
  sem_init(&sem,0,0);//sem=0
  ret=pthread_create(&tid,NULL,fun,(void *)str);
  if(ret<0)
  {
	printf("creat thread failure\n");
	return -1;
  }
  for(i=0;i<10;i++)//first 
  {
	usleep(100);
	printf("this is main fun i=%d\n",i);
  }
  //v
  sem_post(&sem);
  while(1);
  return 0;
}

在这里插入图片描述
利用信号灯集实现同步通信

#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
//#include "semaphore.h"
#include "sys/ipc.h"
#include "sys/sem.h"
#include <unistd.h>
//sem_t sem;
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) */
};

int semid;
union semun mysemun;
struct sembuf mysembuf;
void *fun(void *var)//child thread code
{
  int j;
  //p  wait
 // sem_wait(&sem);  //sleep
  mysembuf.sem_op=-1;
  semop(semid,&mysembuf,1);
  for(j=0;j<10;j++)//second
  {
    usleep(100);
	printf("this is fun j=%d\n",j);
  } 
}
int main()//main thread code
{
  int i;
  char str[]="hello linux\n";
  pthread_t tid;
  int ret;
  semid=semget(IPC_PRIVATE,3,0777);
  if(semid < 0)
  {
	printf("creat semaphore failure\n");
	return -1;
  }
  printf("creat semaphore sucess,semid=%d\n",semid);
  system("ipcs -s");
  mysemun.val=0;
  semctl(semid,0,SETVAL,mysemun);
  //sem_init(&sem,0,0);//sem=0
  mysembuf.sem_num=0;
  mysembuf.sem_flg=0;
  ret=pthread_create(&tid,NULL,fun,(void *)str);
  if(ret<0)
  {
	printf("creat thread failure\n");
	return -1;
  }
  for(i=0;i<10;i++)//first 
  {
	usleep(100);
	printf("this is main fun i=%d\n",i);
  }
  //v
 // sem_post(&sem);
  mysembuf.sem_op=1;
  semop(semid,&mysembuf,1);
  while(1);
  return 0;
}

在这里插入图片描述

之前我们是通过posix中的信号量在操作,后来我们是通过IPC机制的sem灯在操作。

接下来我们通过ftok函数用信号灯集实现无亲缘关系的通信。
clinet.c

 #include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
//#include "semaphore.h"
#include "sys/ipc.h"
#include "sys/sem.h"
#include <unistd.h>
//sem_t sem;
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) */
};

int semid;
union semun mysemun;
struct sembuf mysembuf;
int main()//main thread code
{
  int i;
  int key;
  key=ftok("./a.c",'a');
  if(key < 0)
  {
	printf("creat key failure\n");
	return -1;
  }
  printf("creat key sucess \n");
  semid=semget(key,3,IPC_CREAT | 0777);//IPC_EXCL
  if(semid < 0)
  {
	printf("creat semaphore failure\n");
	return -2;
  }
  printf("creat semaphore sucess,semid=%d\n",semid);
  system("ipcs -s");
  //init sem
  mysemun.val=0;
  semctl(semid,0,SETVAL,mysemun);

  mysembuf.sem_num=0;
  mysembuf.sem_flg=0;
  //P   wait
  mysembuf.sem_op=-1;
  semop(semid,&mysembuf,1);
  for(i=0;i<10;i++)//second 
  {
	usleep(100);
	printf("this is main fun i=%d\n",i);
  }
  //V
  //mysembuf.sem_op=1;
  //semop(semid,&mysembuf,1);
  while(1);
  return 0;
}

server.c

#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
//#include "semaphore.h"
#include "sys/ipc.h"
#include "sys/sem.h"
#include <unistd.h>
//sem_t sem;
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) */
};

int semid;
union semun mysemun;
struct sembuf mysembuf;
int main()//main thread code
{
  int i;
  int key;
  key=ftok("./a.c",'a');
  if(key < 0)
  {
	printf("creat key failure\n");
	return -1;
  }
  printf("creat key sucess \n");
  semid=semget(key,3,IPC_CREAT | 0777);//IPC_EXCL
  if(semid < 0)
  {
	printf("creat semaphore failure\n");
	return -2;
  }
  printf("creat semaphore sucess,semid=%d\n",semid);
  system("ipcs -s");
  //init sem
  //mysemun.val=0;
  //semctl(semid,0,SETVAL,mysemun);

  mysembuf.sem_num=0;
  mysembuf.sem_flg=0;
  for(i=0;i<10;i++)//first 
  {
	usleep(100);
	printf("this is main fun i=%d\n",i);
  }
  //V
  mysembuf.sem_op=1;
  semop(semid,&mysembuf,1);
  while(1);
  return 0;
}

这个时候是我么的客户端先运行,客户端处于一种阻塞的状态,接着运行服务器端时,服务器先打印10条语句,再是客户端打印10条语句。
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值