linux线程、进程(篇幅二)

接linux线程、进程(篇幅一)

进程间通信

----------------------------------------------------------------

进程通信现阶段应用较多的是:内存共享、信号灯、消息队列以及套接字(网络通讯<unix本地回环、internet本地循环>)<unix本地回环、internet本地循环>) 而较为原始的方式有:无名信号、有名信号、以及系统信号(共64个)通信。

》无名管道:适用于有亲缘关系的进程进行通讯,一般仅使用作单工通讯,通过内核存取数据;

》有名管道:任意进程之间半双工通讯,需要同时使用两个可见管道文件,但温江爱你中不存放数据,数据位于内存中;

》信号:异步通讯,借助内核信号实现,仅实现0与1通讯,未涉及数据;

》消息队列:CS(client&server)常用通讯方式,可按数据类型访问,且数据量可自定义,并能设置优先级;

》共享内存:直接对内存操作,效率高,需要在使用方式上稍加注意(同步、互斥机制);

》信号灯:与共享内存一同使用以实现共享内存的同步互斥机制。

从简到繁如下描述:

1、* 无名信号通信 *:文件-->unistd.h 在内核中创建管道文件,管道文件本身不可见,但是可以通过函数创建来使用,函数**pipe**(int fd[2])可以创建单向通讯(单工)的无名管道,入参为整型数组即:int fd[2];返回值是传统Linux:0--成功;-1--失败,输出为,fd中的类文件描述符,fd[0]用于将数据写入,fd[1]用于将数据读出,而且在完成数据读取后,内核中的文件大小为零。 应用范围:父子进程或兄弟进程或祖辈进程 **close**(fd[2])用于关闭这两个文件描述符fd[0]和fd[1]

扫描二维码关注公众号,回复: 2432933 查看本文章

2、* 有名信号通信 *:文件-->unistd.h、fcntl.h、sys/types.h 有名信号通信与无名信号的区别在于创建的管道文件是否可见以及文件的写入读取操作不一样,不同于无名管道的创建方式,无名管道通过使用同一管道文件,从而实现不同进程的通信,适用范围页随之扩大。同时管道文件课件,但其大小在完成一次通讯后为0,原因在于数据在管道文件中不会备份,其位于内存中。**mkfifo**(const char* filename,mode_t mode)filename为指定创建或已有管道文件名。该方式可以实现半双工通信,实现半双工时则需要同时创建两个管道文件用于两个方向的通讯。

3、* 系统信号 * :文件-->signal.h、sys/types.h 系统信号是Linux内核定义的信号,在kill指令中,通过给进程发送信号来实现对进程的控制,如:9号信号是结束当前进程。进程通过信号发送消息时,可以依据需求对系统信号默认处理动作进行修改,利用函数**signal**()设置信号在本进程中的默认处理动作。利用**kill**(pid_t PID,int signal)函数对进程发送信号,**raise**(SIGNAME)向本进程发送信号!

4、* 内存共享 *:文件-->sys/types.h、sys/ipc.h、sys/shm.h 内存共享是在内存中建立一块公共的存储区域,并在每个进程中建立映射关系,使得每个进程对该区域的读写操作具有同等作用效果,从而实现进程的数据通信。共享内存主要有三个部分:

         4.1、创建共享内存标识并建立映射关系:**shmget**(key _ t key,int size,int shmflg(IPC_CREATE|0666));其中key是对共享内存区域的描述关键字,经由**ftok**(const char * fname, int id)函数生成唯一标识或者宏定义 IPC _ PRIVATE交由系统随机,在生成共享内存区域唯一标识符后,则由函数void *shmat(int shmid,NULL,0)完成共享内存映射;

       4.2、利用共享内存读写数据:定义一个char或int的指针类型指向共享内存地址,即:int *p=(int *)shmat(~,NULL,0)或者char *p=(char *)shmat(~,NULL,0),随后对p进行赋值或其他操作后,在另外一个进程中也同样能读取到这些数据;

          4.3、取消映射关系或删除共享内存:在完成数据通信需要清理资源占用时,则利用函数**shmdt**(const void *shmaddr)删除映射关系,**shmctl**(int shmid,int cmd(IPC _ RMID)struct shmid_ds *buf)删除共享内存资源占用。

5、* 消息队列 *:文件 -->sys/types.h、sys/ipc.h、sys/msg.h 创建消息队列:int **msgget**(key_t key,int flag); 添加消息:int **msgsnd**(int msqid,const void *msgp,size_t size,int flag); 读取消息:int msgrcv(int msgid,void *msgp,size_t size,long msgtype,int flag); 控制消息队列:int msgctl(int msgqid,int cmd,struct msqid_ds *buf); 消息队列传输数据可以依据数据类型进行存取,如果不指定数据类型,则依据先进先出原则。 消息队列是数据容量相对较高、操作自由度稍大的一种进程通讯方式,嵌入式系统uCOS中使用名为邮箱消息队列的方式来完成任务之间的通讯,Linux下则可以通过ipcs指令查看当前系统中使用的共享内存、消息队列、信号量等的使用情况。

6、* 系统信号灯 *(system V):文件-->sys/types.h、sys/ipc.h、sys/sem.h 创建或打开:semget(key_t key,int nsems,int semflg); 操作信号灯:semop(int semid,struct sembuf *opsptr,size_t nops); struct sembuf { short sem_num; short sem_op; short sem_flg; }; 获取、删除、设置信号灯:semctl(int semid,int semnum,int cmd<union semun arg>);

基础知识,仅作参考,更多信息请通过‘man’获取。

猜你喜欢

转载自blog.csdn.net/amddma/article/details/81200271