内容简介:APUE 学习笔记——进程间通信
管道
1、管道的局限性有哪些?
- 半全工通信
- 只能在具有公共祖先的进程间通信
2、管道的输入与输出?
fd[0] 为读而打开, fd[1] 为写而打开
3、管道的端口关闭对写入读出的影响?
- 当读一个写端已经被关闭的管道时,在所有数据都被读取后,read 返回 0.
- 如果写一个读端已经被关闭的管道,则产生信号 SIGPIPE
- PIPE_BUF 规定了内核的管道缓冲区大小,写的数据要小于 PIPE_BUF,否则有可能会与其他进程数据相互交互。
4、什么是协同进程?
当一个过滤程序既产生某个过滤程序的输入,又读取该过滤程序的输出时,它就是协同进程。
API
int pipe(int fd[2]);
命名管道
1、open
一个 FIFO
时,阻塞与非阻塞的区别是什么?
- 阻塞打开一个 FIFO 时,只读 open 要阻塞到某个其他进程为写而打开这个 FIFO 为止。类似地,只写 open 要阻塞到某个其他进程为读而打开它为止
- 如果指定了 O_NONBLOCK,则只读立刻返回。但是,如果没有进程为读而打开,那么只写 open 将会返回 -1,并将 ERROR 设置为 ENXIO
API
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);
POSIX 消息队列
1、 POSIX 消息队列与 System V 消息队列的区别?
- POSIX 消息队列总是返回最高优先级的最早信息,System V 则可以返回任意优先级的消息
- 当向一个空队列放置一个消息时,POSIX 消息队列允许产生一个信号或启动一个线程
2、POSIX 消息队列的属性有哪些?
- 是否阻塞
- 队列最大消息数
- 队列每个消息最大 size
- 当前队列消息
3、POSIX 消息队列的限制有哪些?
- mq_mqxmsg 队列中的最大消息数
- mq_msgsize 给定消息的最大字节数
- MQ_OPEN_MAX 一个进程打开的消息队列数目
- MQ_PRIO_MAX 最大优先级
4、POSIX 消息队列异步事件通知的若干规则?
- 如果 notification 参数非空,那么当前进程希望被注册为接受该队列的通知
- 如果 notification 参数为空,而且当前进程已经被注册接受通知,那么当前进程将会取消注册
- 任何时刻只有一个进程可以被注册
- mq_receive 调用中的阻塞比任何注册都优先
- 当该通知被发送给注册进程之后,其注册即将被撤销,必须再次注册
5、在消息队列 notify 信号处理中,为什么推荐使用非阻塞模式读取消息队列?
如果有两个消息先后到达消息队列中,如果使用阻塞模式只能读取第一条消息(循环读很可能会造成阻塞,只能等待 notify
信号),这时 notify 信号不会再产生;如果使用非阻塞模式可以循环读取消息,直到mq_receive 返回 0,然后再等待消
息队列 notify 信号
6、POSIX 实时信号的特征是什么?
- 如果需要实时信号,我们必须使用 SIGRTMIN 到 SIGRTMAX 范围内信号,而且在安装信号处理过程中必须给 sigaction 指定 SA_SIGINFO
- 信号是排队的
- 当有多个 SIGRTMIN 到 SIGRTMAX 范围内信号排队时,值小的信号先于值较大的信号递交
-
当某个非实时信号递交时,传递给它的信号处理函数唯一参数是该信号的值,实时信号则携带更多的信息:
void func(int signo, siginfo_t info, void context)
API
mqd_t mq_open(const char *name, int oflag, ... /* mode_t mode, struct mq_attr *attr)
int mq_close(mqd_t mqdes)
int mq_unlink(const char *name)
int mq_getattr(mqd_t mqdes, struct mq_attr *attr)
int mq_setattr(mqd_t mqdes, const struct *attr, struct mq_attr *oattr)
int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio)
int mq_receive(mqd_t mqdes, char *ptr, size_t len, unsiged int *priop)
int mq_notify(mqd_t mqdes, const struct sigevent *notification)
POSIX 信号量
1、信号量的三种操作是什么?
- 创建信号量。要求调用者指定初始值。
- 等待信号量。如果其值小于或等于 0,那就等待;一旦其值变为大于 0,就将其减 1.
- 挂出信号量。将该信号加 1.
2、信号量与互斥锁、条件变量的区别?
- 互斥锁只能由锁住它的线程解锁,信号量的挂出却不必同一进程进行。
- 互斥锁要么被锁住,要么被解开
- 当一个信号量发送信号时,没有线程等待,那么信号将会丢失;由于信号量与其计数值相关联,信号量的挂出行为总是被记住。
3、POSIX 信号量的两种类型?
有名信号量与基于内存的信号量(无名信号量)
4、信号量限制
- SEM_NSEMS_MAX 一个进程同时打开的最大信号数
- SEM_VALUE_MAX 一个信号量的最大值
API
sem_t *sem_open(const char *name,int oflag, ... /* mode_t mode, unsigned int value */);
int sem_close(sem_t *sem);
int sem_unlink(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_getvalue(sem_t *sem);
int sem_init(sem_t *sem, int shared, unsigned int value);
int sem_destroy(sem_t *sem);
POSIX 共享内存区
1、POSIX 共享内存的两个方法是什么?
- 内存映射文件:由 open 函数打开,调用 mmap
- 共享内存区对象: 由 shm_open 打开一个 POSIX IPC 名字,调用 mmap
API
shm_open(const char *name, int oflag, mode_t mode);
shm_unlink(const char *name)
以上所述就是小编给大家介绍的《APUE 学习笔记——进程间通信》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。