Linnux信号量函数及应用
概述:
信号量(semzphore)与ipc结构不同,他是计数器。信号量用于实现进程的互斥与同步,而不是用于存储进程间通讯数据。说白了,信号量是用来控制进程间的通讯的,实现两个进程或多个进程之间的信息交互的先后起到重要作用。
1、特定
a、信号量用于进程同步,若要在进程传递需要结合共享内存。
b、信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作。
c、每次对信号量的PV操作不仅限于对信号量值加1或减1,而且可以加任意整数。
d、支持信号量组。
e、信号量应用步骤:创建信号量—初始信号量—PV操作(对信号量值加1或减1)达到控制进程先后运行的效果。
2、创建信号量semget()函数原型:
简单的信号量控制常见一种形式只取0和1的为变量,叫二值信号量。而多个正整数信号被称作通用信号量。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
创建信号量;创建成功返回信号量集ID,失败返回-1
参数:
key :键值
nsems: 信号量集个数
semflg:获取|创建IPC_CREAT|0666
3、初始化信号量semctl()函数原型:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
//初始化信号量
参数:
1、 semid : 信号量集id
2、semnum:操作第几个信号量集
3、cmd :初始化,SETVAL 设置信号量的值
4、 ... :设置SETVAL需要配置第四个参数,第四个参数是一个联合体
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) */
};
4、对信号量操作semop()函数原型:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
//对信号量操作
对信号量操作,改变信号量的值,成功返回0,失败返回-1
参数:
semid :信号量集id
*sops :配置信号量集 (结构体)
nsops :配置信号量集的个数
sops[n]结构体如下:
n为信号量集个数
struct sembuf sops[2];
int semid;
/* Code to set semid omitted */
配置以下三个参数:
sops[0].sem_num = 0; 第几个信号量 /* Operate on semaphore 0 */
sops[0].sem_op = 0; 操作信号量赋值 /* Wait for value to equal 0 */
sops[0].sem_flg = SEM_UNDO (设置为阻塞)
sops[1].sem_num = 0; /* Operate on semaphore 0 */
sops[1].sem_op = 1; /* Increment value by one */
sops[1].sem_flg = 0
共享内存配合信号量的应用demo:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
// int semget(key_t key, int nsems, int semflg);
// int semctl(int semid, int semnum, int cmd, ...);
// 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 getkey(int semid)
{
struct sembuf sops;
sops.sem_num =0;
sops.sem_op =-1;
sops.sem_flg = SEM_UNDO;
semop(semid, &sops,1);
}
void putkey(int semid)
{
struct sembuf sops;
sops.sem_num = 0;
sops.sem_op = 1;
sops.sem_flg = SEM_UNDO;
semop(semid, &sops,1);
}
int main()
{
key_t key;
int semid;
char *p = (char *)malloc(sizeof(char)*1024*5);
key = ftok(".",999);
semid = semget(key,1 ,IPC_CREAT|0666);
union semun get;
get.val = 0 ;
semctl(semid,0,SETVAL,get);
int shmid = shmget(key,1024*5, IPC_CREAT|0666);
p = shmat(shmid,0, 0);
int pid = fork();
if (pid >0){
while(1){
getkey(semid);
printf("fatherget:%s\n",p);
// printf("tis is father\n");
printf("\n");
strcpy(p,"connet sucess!");
putkey(semid);
}
}else if(pid == 0){
while(1){
strcpy(p,"qing qiu connet...");
// printf("tis is childer\n");
printf("\n");
putkey(semid);
getkey(semid);
printf("childerget:%s\n",p);
sleep(2);
}
}
system("pause");
return 0;
}
运行显示:
CLC@Embed_Learn:~$ ./sem
fatherget:qing qiu connet...
childerget:connet sucess!
fatherget:qing qiu connet...
childerget:connet sucess!
fatherget:qing qiu connet...
childerget:connet sucess!