进程之间的通信

fork:
僵尸进程:
什么僵尸进程,如何避免僵尸进程?
   一般来说,父进程需要跟踪子进程的退出状态,所以子进程结束之后,父进程读取其退出状态之前,该子进程处于僵尸状态,还有一种是,父进程先于子进程结束,则子进程处于僵尸状态。
    父进程可以通过调用wait()函数避免僵尸进程。因为wait()函数(阻塞的)将等待子进程结束运行,并捕获子进程的退出状态。
    也可以通过调用waitpid()函数(非阻塞的),如果pid指定的子进程没有结束或者意外终止,则waitpid()返回0;如果正常退出,则返回子进程的PID; 调用失败,返回-1。
     实现机制:当一个进程结束,它会给父进程发送SIGCHLD信号。
exec:一般是用fork创建出子进程,然后用exec替换掉
管道:

有名管道和无名管道的区别:
1、有名在无关联进程间使用。无名只可以在有父子进程间使用。
2、有名是全双工的,无名是半双工的。
信号量:

使用信号量步骤:
1、semget:创建一个信号量集/获取一个已经存在的信号量集
函数: int semget(key_t key,int num_sems,int sem_flags);
     key:键值,标识全局唯一的一个信号量集。如果设置为IPC_PRIVATE(值为0),无论该信号量是否存在都创建新的,其他进程也有权访问这个信号量
     num_sems:创建/获取的信号量集中信号量的数目,如果是获取,则为0;
     sem_flags:信号量的权限。
     返回值:成功返回信号量集的标识符,失败返回-1。
2、semop:改变信号量的值,P、V操作。
函数:int semop(int sem_id,struct sembuf* sem_ops,size_t num_sem_ops)
     sem_id:信号量集标识符
     struct sembuf
     {
           unsigned short int sem_num;//信号量的编号,从0开始
           short int sem_op;//操作类型,正整数、0、负整数
           short int sem_flg;//IPC_NOWAIT(无论成功与否立即返回)、SEM_UNDO(进程退出取消操作)
     }
     num_sem_ops:要操作的个数。
     返回值:成功返回0,失败-1。
3、semctl:对信号量进行直接控制。
     int semctl(int sem_id,int sem_num,int command,...)
     command:执行的动作。
共享内存
概念: 共享内存是被多个进程共享的一部分物理内存。共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。

共享内存的实现分为两个步骤:
一、 创建共享内存,使用shmget函数。
二、 映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数。
创建共享内存
int shmget(key_t key ,int size,int shmflg)
     key标识共享内存的键值:0/IPC_PRIVATE。当key的取值为IPC_PRIVATE,则函数shmget将创建一块新的共享内存;
     如果key的取值为0,而参数中又设置了IPC_PRIVATE这个标志,则同样会创建一块新的共享内存。
     size:共享内存的大小
     shmflg:共享内存权限
     返回值:如果成功,返回共享内存表示符,如果失败,返回-1。
映射共享内存
     void* shmat(int shm_id,const void* shm_addr,int flag)
     shmid:shmget函数返回的共享存储标识符
     shm_addr:指定将共享内存关联到进程的哪块物理地址
     flag:决定以什么样的方式来确定映射的地址(通常为0)
     返回值:如果成功,则返回共享内存映射到进程中的地址;如果失败,则返回-1。
共享内存解除映射:当一个进程不再需要共享内存时,需要把它从进程地址空间中多里。
int shmdt(const void *shmaddr)
     返回值:成功返回0,失败返回-1。
控制共享内存的属性:
int shmctl(int shm_id,int command,struct shmid_ds *buf)
消息队列
概念: 消息队列是两个进程之间传递二进制数据的一种简单有效的方式。它的存储形式是链表队列,每个数据块都有特定的类型,接收方可以根据类型来有选择的接收数据,而不一定要像管道和有名管道那样非要先进先出。

使用步骤:
1、创建消息队列
     int msgget(key_t key,int msgflg)
     返回值:成功返回消息队列的标识符,失败返回-1
2、添加消息到消息队列
     int msgsnd(int msgid,const void* msg_ptr,size_t msg_sz,int msgflg)
     msg_ptr:指向要发送的消息,包括消息类型和消息数据。
     msg_sz:消息的数据部分的长度。
     msgflg:行为
3、从消息队列中获取消息
     int msgrcv(int msgid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflg)
     msg_ptr:存储接收的消息
     msgtype:接收何种类型的消息。
4、控制消息队列的属性
     int msgctl(int msgid,int command,struct msgid_ds *buf); 
ipcs:观察当前系统拥有哪些共享资源实例
ipcm:删除当前系统遗留的共享资源

在进程间传递文件描述符:
fork()调用之后,父进程打开的文件描述符在子进程中也是打开的,传递文件描述符并不是传递一个文件描述符的值,而是在接收金成中创建一个新的文件描述符,然后该描述符指向内核中相同的文件表项。
如何在两个不相干的进程之间传递文件描述符呢?
unix socket的sendmsg。传输用辅助数据项msg_control,传输类型用SCM_RIGHTS。

参考资料:《Linux高性能服务器编程》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值