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)
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!