个人技术分享

目录

1、IPC简介

1.1、共享内存

1.1.1 创建/访问共享内存

1.1.2  映射

1.1.3 解除映射

1.1.4  删除/修改共享内存

1.2 信号量集

1.2.1 创建信号量集合

1.2.2 信号量的初始化

1.2.3  信号量的还原和消耗

1.3 消息队列

1.3.1 概念

1.3.3 添加消息队列

1.3.4 读取消息


1、IPC简介

IPC全称:Inter-Process Communication

功能:进程间通信多运用于多进程之间其中包括:共享内存,信号量集,消息队列;

查看系统的IPC的指令:

ipcs

分开查看:

        共享内存         Shared   memory   ipcs -m         函数 shm 开头的
        信号量集         Semaphore set      ipcs -s           函数 sem 开头的
        消息队列         Message Queue    pcs -q           函数 msg 开头的

删除:

        删除共享内存         ipcrm -m         共享内存的 id
        删除信号量集         ipcrm -s          信号量集的 id
        删除消息队列         ipcrm -q          消息队列的 id

获得键值:
        存在的意义:保证多个进程访问的共享内存是同一个;或者多个进程访问的信号集是同一个,再或者多个进程访问的消息队列是同一个;

头文件:

# include <sys/types.h>
# include <sys/ipc.h>

函数原型:

key_t ftok(const char *pathname, int proj_id);

参数:
        pathname:任何的存在的路劲/文件夹名;"/home/xxx"

        proj_id:任意一个0-255之间的数值;

返回值:当成功执行的时候,一个key_t值将会被返回,否则 -1被返回

1.1、共享内存

1.1.1 创建/访问共享内存

作用:用来获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域

头文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

函数原型:

int shmget(key_t key, size_t size, int shmflg);

参数:

        key:键值,用ftok()获得;//任意进程均可使用

        size:共享内存的大小

        shmflg:IPC_CREAT|0600

                IPC_CREAT:如果内有就创建,有就直接获取

返回值:成功返回内存段标识符,失败:-1

1.1.2  映射

作用:把共享内存区域映射到调用进程的地址空间中去

头文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

函数原型:

void *shmat(int shmid, const void *shmaddr, int shmflg);

参数:

        shmid:要映射的共享内存区域标识符

        shmaddr:将共享内存映射到指定位置,一般填NULL

        shmflg:默认 0,共享内存可读写

返回值:
        成功:被映射的段地址,失败:返回NULL

1.1.3 解除映射

作用:解除调用用来解除进程对共享区域的映射

头文件:

 #include <sys/types.h>
 #include <sys/shm.h>

函数原型:

int shmdt(const void *shmaddr);

参数:被映射的共享内存段地址

返回值:成功返回0;失败返回-1

1.1.4  删除/修改共享内存

头文件:

#include <sys/ipc.h>
#include <sys/shm.h>

函数原型:

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数:

        shmid:shmget的返回值

        cmd:选择的操作

                IPC_STAT:获取共享内存属性

                IPC_SET:修改共享内存

                IPC_RMID:删除共享内存,此时第三个参数为NULL

返回值:
        成功0,失败-1

补充:
        memcpy-- 内存复制

函数原型:

void *memcpy(void *destin, void *source, unsigned n);

参数:

destin: 指向用于存储复制内容的目标数组, 类型强制转换为 void* 指针。
source-- 指向要复制的数据源, 类型强制转换为 void* 指针。 n-- 要被复制的字节数。
返回值: 该函数返回一个指向目标存储区 destin 的指针。


1.2 信号量集

1.2.1 创建信号量集合

作用:创建一个信号量集或访问一个已存在的信号量集

头文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

   函数原型:

int semget(key_t key, int nsems, int semflg);

   参数:

        key:键值

        nsems:信号量集合中创建几组信号量,通常取值为1;

        semflg:IPC_CREAT 表示若信号量已存在, 返回该信号量标识符; 不存在, 创建; IPC_CREAT|0600

        返回值: 如果成功, 则返回信号量集的 IPC 标识符。 如果失败, 则返回-1


1.2.2 信号量的初始化

头文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

函数原型:

int semctl(int semid, int semnum, int cmd, ...);

参数:

        semid:是由semget返回的信号量标识符

        sumnum:你要操作的信号量集合中信号量的下标,第一组的下标是0;

        cmd:

                删除:IPC_RMID( 立即删除信号集, 唤醒所有被阻塞的进程)
                设置: SETVAL( 根据 semnum 指定的编号设定相应信号的值, 此时需要填充第四个参数(用联合体中 val 成员的值设置信号量集合中单个信号量的值))
                获取: GETVAL( 根据 semnum 指定的编号返回相应信号的值, 此时该函数返回值就是你要获得的信号量的值, 不再是 0 或-1)

如果有第四个参数类型
union semun {
        short val; /*SETVAL 用的值*/
        struct semid_ds* buf; /*IPC_STAT、 IPC_SET 用的 semid_ds 结构(则是一个内核结构体)*/
        nsigned short* array; /*SETALL、 GETALL 用的数组值*/
        struct seminfo *buf; /*为控制 IPC_INFO 提供的缓存(表示信号量系统资源配置信息)*/
} arg;
返回值
        成功: 返回相应的值, 失败: 返回-1

举例:

key = ftok();
semid = semget(key,1,IPC_CREAT|0600);
union semun text;
text.val = 1;//二值信号量
semctl(semid,0,SETVAL,text);

1.2.3  信号量的还原和消耗

        用于改变信号量对像中各个信号量的状态

函数原型:

int semop(int semid, struct sembuf *sops, unsigned nsops);

参数: semid: semget 返回值
                sops: 对信号量的操作
                struct sembuf{
                        unsigned short sem_num; //信号量的下标 0
                        short sem_op; //操作类型 +1 -1
                        sem_op > 0 信号加上 sem_op 的值, 表示进程释放控制的资源;
                        sem_op < 0 信号减去 sem_op 的值。
                        short sem_flg; //操作标志 0 设置信号量的默认操作
                        }
        nsops: 进行操作信号量的个数, 即 sops 结构变量的个数, 需大于或等于 1。 最常见设置此值
等于 1, 只完成对一个信号量的操作
返回值: 成功时, 返回 0; 失败时, 返回-1

1.3 消息队列

1.3.1 概念

        消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向其中按照一定的规则添加新信息,对消息队列有读权限的进程则可以从消息队列中读走消息。和队列的特点一样,遵从先进先出的原则。

1.3.2 创建新的消息队列获取已存在的消息队列

头文件:

#include <sys / types.h>
#include <sys / ipc.h>
#include <sys / msg.h>

函数原型:

int msgget(key_t key, int msgflg);

参数:key由ftok生成。

        msgflg:IPC_CREAT|0600

IPC_CREAT 值, 若没有该队列, 则创建一个并返回新标识符; 若已存在, 则返回原标识
符。
返回值:

成功执行:返回消息队列标识符。失败返回-1.

1.3.3 添加消息队列

作用:把消息添加到已打开的消息队列末尾(尾差法)。

函数原型:

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

参数:

        msgid:值明消息队列的ID,通常是msgget 函数成功的返回值

        msgp:发送数据缓冲区首地址,指向消息结构的指针。

该消息结构 msgbuf 为:
struct msgbuf{
        long mtype;//消息类型
        char mtext[1];//消息正文:可以是数值/数组/结构体
}

消息必须是一个结构体, 并且结构体的第一个成员必须是消息类型(long);

msgsz: 数据大小, 注意, 改大小仅仅是数据大小, 需要用结构体整体大小减去消息类型
的大小, 每个消息体最大不要超过 4K;

sizeof(struct msgbuf) - sizeof(long);

        msgflg: 一般赋 0, 阻塞方式
        IPC_NOWAIT : 非阻塞
返回值: 成功则返回 0, 出错则返回-1

1.3.4 读取消息

        作用:把消息从消息队列中取走,与FIFO不同的是,这里可以指定取走某种类型的消息(在该类型的消息中,依旧是FIFO)

函数原型:

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

参数:

msqid : 消息队列的队列 ID

msgp: 消息缓冲区 -- 提供空间 -- 结构体类型
msgsz: 消息的字节数 -- sizeof(结构体)-sizeof(long);
msgtyp: 消息类型
        =0 忽略类型
        >0 只接收指定类型的数据
        <0 只接受小于等于其绝对值的数据

msgflg: 0: msgsnd 调用阻塞直到条件满足为止
IPC_NOWAIT 不阻塞
返回值: 接收成功返回 0, 失败返回-1
1.3.5 控制消息队列

函数原型:

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

参数:

        msqid: 消息队列的队列 ID
        cmd:

                IPC_STAT: 读取消息队列的属性 msqid_ds, 并将其存储在 buf 指定的地址中
                IPC_SET: 设置消息队列的属性 msqid_ds 中的 ipc_perm 元素的值。 这个值取自 buf 参数。
                IPC_RMID: 从系统内核中移走消息队列, 此时最后一个写 NULL
                Buf: 消息队列缓冲区

返回值:接收成功返回0,失败返回-1.