信号量
定义信号变量; sem_t sem1 sem2
初始化信号量
P操作
V操作
功能
|
信号量(POSOX)
|
信号量灯(IPC)
|
定义信号变量
|
sem_t sem1
|
semget
|
初始化信号量
|
sem_init
|
semctl
|
P操作
|
sem_wait
|
semop
|
V操作
|
sem_post
|
semop
|
多 线程中的信号量例子:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
#define N 64
sem_t sem;
void * f(void *arg)
{
while (1)
{
sem_wait(&sem);
sleep(1);
printf("%s", (char *)arg);
}
}
int main()
{
pthread_t thread;
char buf[N]; //= "you are welcome";
void *thread_result;
if (sem_init(&sem, 0, 0) == -1)
{
perror("sem_init");
exit(-1);
}
if (pthread_create(&thread, NULL, f, buf) != 0)
{
fprintf(stderr, "pthread_create %s\n", strerror(errno));
exit(-1);
}
do
{
printf("input:");
fflush(stdout);
fgets(buf, N, stdin);
sem_post(&sem);//唤醒子线程 V操作
} while (strncmp(buf, "quit", 4));
return 0;
}
信号灯:
信号灯集合(可以包含多个信号量) IPC对象是一个
信号灯集 (含有多个信号量)
所有的函数是对一个集合的操作:
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
|
所需头文件
| #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: 要操作的信号灯的个数
|
所需头文件
| #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(设置对象属性)
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) */
};
server.c端
#include "stdio.h"
#include "sys/ipc.h"
#include "sys/sem.h"
#include "sys/types.h"
#include "stdlib.h"
/*联合体*/
union semun
{
int val; //SETVAL:设置信号灯的值
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int main()
{
int i;
int key;
int semid;
union semun mysemun;
struct sembuf mysembuf;
key=ftok("./a.c",'a');//touch a.c记得每次要先创建a.c
if(key < 0)
return -1;
semid=semget(key,2,IPC_CREAT | 0777);// 创建信号灯集
if(semid < 0)
return -2;
mysemun.val=0;//初始化信号灯
semctl(semid,0,SETVAL,mysemun);//初始化信号灯集,也可以删除信号灯;
/*先运行*/
for(i=0;i< 10 ;i++)
{
printf("this is first process\n");
sleep(1);
}
/*运行完以后进行唤醒 v操作*/
mysembuf.sem_num=0;
mysembuf.sem_op=1;//信号灯v操作
mysembuf.sem_flg=0;
semop(semid,&mysembuf,1);
return 0;
}
client.c端
#include "stdio.h"
#include "sys/ipc.h"
#include "sys/sem.h"
#include "sys/types.h"
#include "stdlib.h"
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int main()
{
int i;
int key;
int semid;
union semun mysemun;
struct sembuf mysembuf;
key=ftok("./a.c",'a');
if(key < 0)
return -1;
semid=semget(key,2,IPC_CREAT | 0777);
if(semid < 0)
return -2;
/*后运行不需要在初始化*/
//mysemun.val=0;
//semctl(semid,0,SETVAL,mysemun);
//
mysembuf.sem_num=0;
mysembuf.sem_op=-1;//信号灯p操作
mysembuf.sem_flg=0;
semop(semid,&mysembuf,1);
for(i=0;i< 10 ;i++)
{
printf("this is second process\n");
sleep(1);
}
return 0;
}