IPC,Inter-Process Communication,进程间通信
ipcs : 查看当前系统的IPC机制使用情况
IPC进程间通信机制的料不多,信号量是一个比较难得点,但是要根据实际项目的场景进行分析,纸上谈兵是没有意义的。
通过种子文件获取KEY_L的值
如果各个进程都需要获取相同的IPC对象的ID,因此需要相同的KEY_L,也就是IPC秘钥,可以通过ftok函数来获取相同的key,使用方法很简单
- 在目录下建立一个种子文件,注意不能删除这个文件
- 所有的进程都调用ftok,第一个参数就是这个文件的路径和名字,第二个参数调相同的值,不为0即可
信号量的小工具分享
- 分享一个信号量小工具,包括了信号量的所有操作
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.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
};
/* 创建信号量 */
int sem_creat(key_t key)
{
int semid;
semid = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL);
if (semid == -1)
{
perror("semget error");
return -1;
}
return semid;
}
/* 删除信号量 */
int sem_delete(int semid)
{
semctl(semid, 0, IPC_RMID, NULL);
return 0;
}
/* 打开信号量 */
int sem_open(key_t key)
{
int semid;
semid = semget(key, 1, 0666);
if (semid == -1)
{
perror("semget error");
return -1;
}
return semid;
}
/* 设置信号量的值 */
int sem_setval(int semid, int val)
{
int ret;
union semun su;
/* 表示资源的个数 */
su.val = val;
ret = semctl(semid, 0, SETVAL, su);
if (ret == -1)
{
perror("semctl error");
return -1;
}
return 0;
}
/* 获取信号量的值 */
int sem_getval(int semid)
{
int val = 0;
val = semctl(semid, 0, GETVAL, NULL);
if (val == -1)
{
perror("semctl error");
return -1;
}
printf("val : %d \n", val);
return 0;
}
/* 信号量p操作 */
int sem_p(int semid)
{
struct sembuf sp = {0, -1, 0};
semop(semid, &sp, 1);
return 0;
}
/* 信号量v操作 */
int sem_v(int semid)
{
struct sembuf sv = {0, 1, 0};
semop(semid, &sv, 1);
return 0;
}
/* 获取信号量权限 */
int sem_getmode(int semid)
{
int ret;
int val;
struct semid_ds buf;
ret = semctl(semid, 0, IPC_STAT, &buf);
if (ret == -1)
{
perror("semctl error");
return -1;
}
val = buf.sem_perm.mode;
printf("mode : 0%o \n",val);
return val;
}
/* 设置信号量权限 */
int sem_setmode(int semid, int mode)
{
int ret;
struct semid_ds buf;
buf.sem_perm.mode = mode;
ret = semctl(semid, 0, IPC_SET, &buf);
if (ret == -1)
{
perror("semctl error");
return -1;
}
return 0;
}
void usage()
{
fprintf(stderr,"semtool -c 创建信号量\n");
fprintf(stderr,"semtool -d 删除信号量\n");
fprintf(stderr,"semtool -p 信号量p操作\n");
fprintf(stderr,"semtool -v 信号量v操作\n");
fprintf(stderr,"semtool -s<val> 信号量设置初始值\n");
fprintf(stderr,"semtool -g 获取信号量的值\n");
fprintf(stderr,"semtool -f 打开权限\n");
fprintf(stderr,"semtool -m<mode> 设置权限\n");
}
int main(int argc, char *argv[])
{
int opt;
opt = getopt(argc, argv, "cdpvs:gfm:");
if (opt == -1)
{
usage();
exit(EXIT_FAILURE);
}
key_t key;
key = ftok(".",'s');
int semid;
switch (opt)
{
case 'c':
semid = sem_creat(key);
break;
case 'd':
semid = sem_open(key);
sem_delete(semid);
break;
case 'p':
semid = sem_open(key);
sem_p(semid);
sem_getval(semid);
break;
case 'v':
semid = sem_open(key);
sem_v(semid);
sem_getval(semid);
break;
case 's':
semid = sem_open(key);
sem_setval(semid, atoi(optarg));
sem_getval(semid);
break;
case 'g':
semid = sem_open(key);
sem_getval(semid);
break;
case 'f':
semid = sem_open(key);
sem_getmode(semid);
break;
case 'm':
semid = sem_open(key);
sem_setmode(semid, atoi(optarg));
break;
case '?':
usage();
break;
}
return 0;
}
可以使用这个小工具进行信号量的创建,使用,删除,pv操作,运行结果:
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!