栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux系统编程之进程通信(学习笔记)

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux系统编程之进程通信(学习笔记)

Linux系统编程中,进程通信常用的有六种:管道,信号,IPC通信中的共享内存、消息队列、信号量集

 

一、无名管道(只用于有亲缘关系的进程、并且无文件节点)

int pipe(int pipefd[2]) 创建一个无名管道

pipefd[0] 代表读 pipefd[1] 代表写

有读写阻塞

二、有名管道(有文件节点)

1、可以通过mkfifo函数打开一个有名管道,也可以直接当作命令行来创建

2、只能通过文件io进行读写

3、有读写阻塞

 

三、标准流管道(只能通过标准io读写)

FILE *popen(const char *command,const char *type); 打开一个标准流管道

int pclose(FILE *stream) 关闭一个标准流管道

 

四、信号

kill -l 查看所有信号

信号9和信号19不能被更改

较常使用的信号:

 SIGINT:用户按下组合 Ctrl 键+c 键时,向正在运行的进程发送一则信号。默认动作为终止进程。 

  SIGALRM:定时器超时,超时的时间由系统调用 alarm 设置。可以理解为闹钟,时间到了默认动作为终止进程。 

  jobs命令 可以查看现有暂停的任务

  fg命令可以继续暂停的任务

  

  //alarm()定时给自身发送闹钟信号 默认是结束进程

头文件:#include

原型:unsigned int alarm(unsigned int senconds);

参数:unsigned int senconds ---》表示设定的时间(单位:秒)

         若你设置为0,相当于取消设定的闹钟

  sighandler_t signal(int signum,sighandler_t handler);信号处理函数

        handler: 第一种:SIG_DFL 对信号采用默认处理方式

         第二种:SIG_IGN 忽略该信号

         第三种:信号处理函数的名称--void 函数名(int arg)

     

五、IPC通信

ipcs 显示所有的ipc对象

ipcs -q 消息队列

ipcs -m 共享内存

ipcs -s 信号量集

ipcrm -大写key -小写id 删除

(1)共享内存

基本单位是4k(4096bytes)

多进程使用共享内存的流程:

第一步:申请一块共享内存

第二步:多进程打开同一块共享内存

第三步:多进程将共享内存映射到自己的进程地址空间地址上。

第四步:多进程通过自己的映射区进行读写,完成通信(间接的使用物理空间的内存)

第五步:多进程取消共享内存在自身进程空间地址的映射。

第六步:删除共享内存

 

 

所需函数原型:

key_t ftok(const char *pathname,int proj_id);获取key值文件跟id可以随便写

int shmget(key_t key,size_t size,int shmflg);申请共享内存

成功则返回共享内存id

shmflg:IPC_CREAT | 0666  //创建并且设置读写权限,如果不给权限,返回的key值为0xffffffff没办法用

 

void *shmat(int shmid,const void *shmaddr,int shmflg); 内存映射到本进程的地址空间上

shmaddr:NULL 自动分配 shmflg:0 可读可写

返回内存应映射后的地址

 

int shmdt(const void *shmaddr);取消内存映射

int shmctl(int shmid,int cmd,struct shmid_ds *buf) 内存控制函数 现阶段主要用于删除内存映射

cmd:IPC_STAT(查看状态) IPC_SET(设置)IPC_RMId(删除)

需要取消内存映射后才可以删除

 

六、消息队列

有编号

先进先出

具有读阻塞

int msgget(key_t key,int msgflg);打开消息队列

msgflg:IPC_CREAT|0600

 

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 消息队列发送函数

成功 返回消息队列的ID,失败的话 返回-1

msgflg:0(保留阻塞)|IPC_NOWAIT(无阻塞)|MAG_ERROR

 第二个参数需要先定义:struct msgbuf {

               long mtype;

               char mtext[20];

           };

 

ssize_t msgrcv(int msqid , void *msgp,size_t msgsz,long msgtyp,int msgflg);消息队列接收函数

msgtyp:接收消息的编号

int msgctl(int msqid,int cmd,struct msqid_ds *buf);消息队列控制函数  现阶段主要用于删除

 

 

七、信号量集/信号灯

信号量是一个非负整数

PV操作是基于对信号量值进行的操作,当信号量值等于0,此进程再使用该信号量的时候会进入阻塞,

当信号量的值大于0时候,此进程使用该信号量才会继续执行。

 

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

int nsems :创建信号量集中的信号量数目,如果引用一个现存的信号量集合,

则将nsems 指定为0。

--也可以为当信号量集里面信号量的数量

int semflg:IPC_CREAT|0600

成功返回信号量集的id

 

int semctl(int semid, int semnum, int cmd, union semun arg);信号量集控制函数

.int semnum: 要操作的信号量集中的指定信号量编号即下标,编号从0开始,

当使用信号量集时才会被用到。

 

cmd:IPC_RMID:从系统中删除信号量。

 

IPC_GETVAL或GETVAL: 根据 semmun 指定的编号返回指定信号量的当前值,

 此时该函数返回值就是你要获得的信号量的值,不再是 0 或-1)

 

 IPC_SETVAL或SETVAL: 根据 semmun 指定的编号设定相应信号的值,修改的值需要使用第四个参数 union semun arg,然后要设置值放arg.val在)

 简单来说就是将信号量值设置为arg的val值

 

 GETALL(获取所有信号量的值,此时该函数第二个参数为0,

 此时需要用到第四个参数union semun arg并且会将所有信号的值存入arg.array所指向的数组(unsigned short)

 的各个元素中(每个元素都对应一个信号量的值))

 

 SETALL(设置所有信号量的值,此时该函数第二个参数为 0,此时需要用到第四个参数union semun arg,

 将 arg.array 指向的数组的所有元素的值一一对应设定到信号量时集中)

 

 

 使用共用体时需要自己定义:

 union semun{

 int val;

 struct semid_ds *buf;

 unsigned short *array;

 struct seminfo *__buf;

}

 

返回值:

成功,根据cmd的值的不同而返回不同的值。

cmd为IPC_STAT、IPC_SETVAL、IPC_RMID则函数返回0。

cmd为IPC_GETVAL则函数返回信号量的当前值。

错误: -1

 

 

int semop(int semid, struct sembuf *sops, unsigned nsops); 操作信号量集

第二个参数:struct sembuf 

{

 unsigned short sem_num;

 short sem_op;

 short sem_flg;

 sem_flg:信号量操作的属性标志 写0表示正常操作

}

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/827433.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号