本文主要分享的关于进程间通信中的管道(有名管道和无名管道)以及信号的概念以及相关的函数操作接口;如pipe,mkfifo,signal,pause,alarm等;
进程的数据分类,同一进程间的线程共享内存地址空间,其中进程用户空间的五个段:
(1)英文: .bss 、.data 、 .text 、 stack 、heap 。
(2)中文:BSS段(bss segment),数据段:数据段(data segment),代码段:代码段(code segment/text segment),栈(stack)(栈又称堆栈), 堆(heap).
线程:【同一进程间的线程共享的资源有4个】
a. 堆 由于堆是在进程空间中开辟出来的,所以它是理所当然地被共享的;因此new出来的都是共享的(16位平台上分全局堆和局部堆,局部堆是独享的)
b. 全局变量 它是与具体某一函数无关的,所以也与特定线程无关;因此也是共享的
c. 静态变量 虽然对于局部变量来说,它在代码中是“放”在某一函数中的,但是其存放位置和全局变量一样,存于堆中开辟的.bss和.data段,是共享的
d. 文件等公用资源 这个是共享的,使用这些公共资源的线程必须同步。Win32 提供了几种同步资源的方式,包括信号、临界区、事件和互斥体。
线程间通信:
1.使用全局变量(注意资源竞争的问题)
进程间通信的方法:
1.管道 2.信号 3.消息队列 4.共享内存 5.信号灯 6.套接字
一、管道
1.无名管道
无名管道就是一段内核缓存区(大小 64k)
只能用于具有亲缘关系的进程间通信(只能是像父子进程)
函数接口:
(1)pipe
int pipe(int pipefd[2]);
功能: 创建一个无名管道
参数:
pipefd[0]:读管道文件描述符
pipefd[1]:写管道文件描述符
返回值:
成功返回0
失败返回-1
特性:
(1)管道中有写端
管道中有数据则直接读出
管道中没有数据阻塞等待数据写入再读出数据
(2)管道中没有写端
管道中有数据则直接读出
管道中没有数据不会阻塞直接返回
(3)管道中有读端
管道中写入数据,如果没有写满则直接写入
如果写满,则等待有数据读出后才能继续写入
(4)管道中没有读端
管道中写入数据,会产生管道破裂
2.有名管道
可以用来进行任意两个进程间的通信
(1)mkfifo
int mkfifo(const char *pathname, mode_t mode);
功能: 创建一个管道
参数:
pathname:管道的名称
mode:管道文件的权限
返回值:
成功返回0
失败返回-1
特性:
必须有读写两端同时加入才能继续向下执行
如果只有读端或者只有写端,程序会阻塞等待另一端加入才能继续向下执行
二、信号:实现两个进程间通信,不能发送数据,只能发送通知
(1)信号的类型:
1.kill -l 查看信号类型
SIGINT:ctrl + c
SIGSEGV:段错误信号
SIGQUIT:ctrl + \
SIGPIPE:管道破裂信号
SIGKILL:不允许被忽略和捕捉
SIGALRM:定时信号
SIGCHLD:子进程退出,父进程收到SIGCHLD信号
SIGTSTP:ctrl + z
SIGIO:异步IO信号
(2)信号的处理方式:
1.忽略:
收到信号,不处理信号
2.缺省:
收到信号,按照默认方式处理信号
3.捕捉:
收到信号,按照指定的方式处理信号(9号 SIGKILL 19号 SIGSTOP不允许被忽略和捕捉)
(3)函数接口:
1.signal
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:修改信号的处理方式
参数:
signum:信号编号
handler:
SIG_IGN 忽略信号
SIG_DFL 默认处理信号
自定义函数指针:捕捉信号并执行指针指向的函数处理信号
返回值:
成功返回上一次设置的信号处理函数
失败返回SIG_ERR
2.pause
int pause(void)
功能:
调用该函数的进程挂起,知道接收到信号(不能把进程杀死)才能继续执行
返回值:
只有在被信号唤醒时才会返回-1
3.alarm
unsigned int alarm(unsigned int seconds);
功能:
定时过了seconds秒后,向调用进程发送SIGALRM信号
参数:
seconds:秒数
返回值:
成功返回上次定时剩余的秒数
前面没有定时返回0
本期的分享就到这里结束了,欢迎各位小伙伴私信留言评论哦!