获取信号量
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/**
* [semget 创建信号量集合]
* @param key [
* key表示获取信号量的key
* IPC_PRIVATE:表示每次获取新的信号量集合,主要用于既有亲缘关系的进程。
非IPC_PRIVATE:在每次获取的时候,key对应的信号量集合不存在则创建并返回id;存在则直接返回已有信号量集合的id
* ]
* @param nsems [信号量集合中信号量的个数]
* @param semflg [
* 信号量的访问权限和创建方式
* IPC_CREAT 没有则创建,有则直接返回;
IPC_CREAT | IPC_EXCL : 没有则创建返回,有则报错;
* ]
* @return [成功返回信号量的id,失败返回-1且修改errno的值]
*/
int semget(key_t key, int nsems, int semflg);
控制
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/**
* [semctl 实现信号量集合中信号量的控制]
* @param semid [信号量集合id]
* @param semnum [信号量在集合中的编号(编号从0开始计数)]
* @param cmd [
* 控制命令,是一个可变参数,需要根据cmd命令选择是否使用第4个参数
* IPC_STAT和IPC_SET 获取或者设置IPC的状态属性;
IPC_RMID 删除IPC对象
GETALL和SETALL 获取和设置信号量集合的属性值;
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) /
};
* ]
* @return [成功返回和cmd相关 失败返回 -1 修改errno值]
*/
int semctl(int semid, int semnum, int cmd,...);
PV操作
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/**
* [semop PV操作]
* @param semid [信号量集合的id]
* @param sops [信号量操作的结构体]
* @param nsops [参数二数组个数]
* @return [成功返回0,失败返回-1]
*/
int semop(int semid, struct sembuf *sops, size_t nsops);
同步实例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
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) */
};
/* P操作 */
int Sem_Wait(int semid)
{
int ret;
struct sembuf mysembuf =
{
.sem_num = 0,/* 信号量集合中信号的序号 */
.sem_op = -1,/* -1表示资源数-1,实现P操作 */
.sem_flg = 0
};
ret = semop(semid, &mysembuf, 1);
if (ret == -1)
{
perror("semop->P");
return -1;
}
return 0;
}
/* V操作 */
int Sem_Post(int semid)
{
int ret;
struct sembuf mysembuf =
{
.sem_num = 0,/* 信号量集合中信号的序号 */
.sem_op = 1,/* 1表示资源数+1,实现V操作 */
.sem_flg = 0
};
ret = semop(semid, &mysembuf, 1);
if (ret == -1)
{
perror("semop->P");
return -1;
}
return 0;
}
int main()
{
key_t key;
int semid;
int ret;
int i;
union semun mysemum;
pid_t pid;
/* 获取信号量的key */
key = ftok(".", 's');
if (key == -1)
{
perror("ftok");
return -1;
}
/* 创建信号量集合 */
semid = semget(key, 1, 0777 | IPC_CREAT);
if (semid == -1)
{
perror("semget");
return -1;
}
mysemum.val = 0;
/* 设置信号量的初始值 */
ret = semctl(semid, 0, SETVAL, mysemum);
if (ret == -1)
{
perror("semctl->SETVAL");
return -1;
}
/* 实现多个任务的同步:子进程执行1次之后父进程才能执行1次 */
pid = fork();
if (pid == -1)
{
perror("fork");
return -1;
}
else if (pid == 0)
{
while(1)
{
sleep(1);
printf("child process\n");
/* 信号量进行V操作 */
Sem_Post(semid);
}
exit(EXIT_SUCCESS);
}
else
while(1)
{
/* 信号量进行P操作 */
Sem_Wait(semid);
printf("parent process\n");
}
/* 删除信号量集合 */
ret = semctl(semid, 0, IPC_RMID);
if (ret == -1)
{
perror("semctl->IPC_RMID");
return -1;
}
}
互斥实例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
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 shm_init(const char *pathname, int proj_id, size_t size, void **shmaddr)
{
key_t key;
int shmid;
/* 获取共享内存的键值 */
key = ftok(pathname, proj_id);
if (key == -1)
{
perror("ftok");
return -1;
}
/* 获取共享内存 */
shmid = shmget(key, size, 0777 | IPC_CREAT);
if (shmid == -1)
{
perror("shmget");
return -1;
}
/* 共享内存的映射 */
*shmaddr = shmat(shmid, *shmaddr, 0);
if (*shmaddr == (void *) -1)
{
perror("shmat");
return -1;
}
return shmid;
}
int shm_del(int shmid, void *shmaddr)
{
int ret;
/* 解除共享内存的映射:不会删除共享内存 */
ret = shmdt(shmaddr);
if (ret == -1)
{
perror("shmdt");
return -1;
}
/* 删除共享内存:从内存中删除 */
ret = shmctl(shmid, IPC_RMID, NULL);
if (ret == -1)
{
perror("shmctl->IPC_RMID");
return -1;
}
return -1;
}
int Sem_Init(const char *pathname, int proj_id, int nsems)
{
key_t key;
int semid;
int ret;
union semun mysemum;
/* 获取信号量的key */
key = ftok(pathname, proj_id);
if (key == -1)
{
perror("ftok");
return -1;
}
system("ipcs -s");
/* 创建信号量集合 */
semid = semget(key, nsems, 0777 | IPC_CREAT);
if (semid == -1)
{
perror("semget");
return -1;
}
mysemum.val = 1;
/* 设置信号量的初始值 */
ret = semctl(semid, 0, SETVAL, mysemum);
if (ret == -1)
{
perror("semctl->SETVAL");
return -1;
}
return semid;
}
/* P操作 */
int Sem_Wait(int semid)
{
int ret;
struct sembuf mysembuf =
{
.sem_num = 0,/* 信号量集合中信号的序号 */
.sem_op = -1,/* -1表示资源数-1,实现P操作 */
.sem_flg = 0
};
ret = semop(semid, &mysembuf, 1);
if (ret == -1)
{
perror("semop->P");
return -1;
}
return 0;
}
/* V操作 */
int Sem_Post(int semid)
{
int ret;
struct sembuf mysembuf =
{
.sem_num = 0,/* 信号量集合中信号的序号 */
.sem_op = 1,/* 1表示资源数+1,实现V操作 */
.sem_flg = 0
};
ret = semop(semid, &mysembuf, 1);
if (ret == -1)
{
perror("semop->P");
return -1;
}
return 0;
}
int main()
{
int ret;
int shmid;
int semid;
char *shmaddr = NULL;
pid_t pid;
/* 共享内存的初始化 */
shmid = shm_init(".", 'm', 256, (void **)&shmaddr);
if (shmid == -1)
return -1;
/* 信号量的初始化 */
semid = Sem_Init(".", 's', 1);
if (semid == -1)
return -1;
pid = fork();
if (pid == -1)
{
perror("fork");
return -1;
}
else if(pid == 0)
{
/* 子进程 */
int len;
int i;
char tmp;
strcpy(shmaddr, "0123456789");
len = strlen(shmaddr);
printf("------------\n");
while(1)
{
Sem_Wait(semid);
for (i = 0; i < len / 2; i++)
{
tmp = shmaddr[i];
shmaddr[i] = shmaddr[len - 1 - i];
shmaddr[len - 1 - i] = tmp;
}
Sem_Post(semid);
}
exit(EXIT_SUCCESS);
}
while(1)
{
Sem_Wait(semid);
printf("%s\n", shmaddr);
Sem_Post(semid);
sleep(1);
}
ret = shm_del(shmid, shmaddr);
if (ret == -1)
return -1;
return 0;
}
网友评论