Foreword:
1. Inter-process communication is divided into three categories:
Early days: unnamed pipes (pipe) , named pipes (fifo) and signals (signal)
System 5 IPC objects: shared memory , message queue, and semaphore
Network : socket
2. Pipeline:
Pipes are a method of process communication in Linux. They connect the output of one program directly to the input of another program. There are two main types of pipeline communication in Linux: named pipes, unnamed pipes, and the pipe file indicator TT.
1. Unnamed pipeline
1. Introduction to nameless pipes:
Unnamed pipes are an original way of Linux communication and have the following characteristics:
(1) Communication can only occur between processes that have a relationship (father-child process or sibling process)
(2) It is simplex (one end receives and one end sends), with fixed reading end and writing end.
(3) The pipe can also be regarded as a special file, and its read(), write() and other functions can also be used for its reading and writing, but it does not belong to any system file and only exists in the memory.
Model:
pipe function:
pipe:创建无名管道
#include <unistd.h>
int pipe(int pipefd[2]);
功能:
创建无名管道
参数:
pipefd[2]:整型数组
存放两个文件描述符:一个负责读 一个负责写
[0]--->读取
[1]--->写入
返回值:
成功返回0
失败返回-1,并设置错误码
2. Test code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(){
//制作无名管道需要用到整型数组 ,一个写,一个读
int pipefd[2];
//创建无名管道 ,返回值为0则创建成功
int ret=pipe(pipefd);
if(ret<0){
perror("pipe");
return -1;
}
printf("[0]:%d\n",pipefd[0]);
printf("[1]:%d\n",pipefd[1]);
//开出父子进程,父子进程依赖无名管道进行通信
pid_t pid=fork();//开出父子进程
if(pid>0){
//父进程的操作 :发送信息给子进程
char buf[50]="";
while(1){
//bzero 清空数组内存垃圾值
bzero(buf,sizeof(buf));
scanf("%s",buf);
write(pipefd[1],buf,strlen(buf));
}
}else if(pid==0){
//子进程的操作,读取无名管道中的内容
char buf[50];
while(1){
bzero(buf,sizeof(buf));
read(pipefd[0],buf,sizeof(buf));
printf("子进程收到:%s\n",buf);
}
}else{
perror("fork");
exit(-1);
}
return 0;
}
3. Note on pipeline reading and writing
2. Famous channels
1. Characteristics of famous pipelines
Named pipes (FIFO) are an improvement over unnamed pipes and have the following characteristics:
(1) Realize communication between two unrelated processes.
(2) The pipe can be pointed out by the path and is visible in the system. After it is established, the two processes can use it as an ordinary file for reading and writing operations.
(3) FIFO strictly follows the first-in-first-out rule and does not support operations (positioning) such as lseek() .
Model:
2. Test:
Communication method 1:
#include <stdio.h>
#include <sys/types.h>//mkfifo头文件
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc,char *argv[]){
if(argc!=2){
printf("User:%s <file_name> \n",argv[0]);
return 0;
}
//创建管道文件(利用某一个文件名只能创建一次的特性)
if(access(argv[1],F_OK)){ //判断argv[1]是否已经存在
if(mkfifo(argv[1],0666)){
perror("mkfifo");
exit(-1);
}
}
//2>利用有名管道进行进程间通信
int fd=open(argv[1],O_RDWR);
if(fd<0){
perror("open");
exit(-1);
}
//3>往有名管道里写入数据
char buf[50]="";
while(1){
bzero(buf,sizeof(buf));
scanf("%s",buf);
write(fd,buf,strlen(buf));
}
return 0;
}
Communication method 2:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc,char *argv[]){
if(argc!=2){
printf("User:%s <file_name> \n",argv[0]);
return 0;
}
//创建管道文件(利用某一个文件名只能创建一次的特性)
if(access(argv[1],F_OK)){ //判断argv[1]是否已经存在
if(mkfifo(argv[1],0666)){
perror("mkfifo");
exit(-1);
}
}
//2>利用有名管道进行进程间通信
int fd=open(argv[1],O_RDWR);
if(fd<0){
perror("open");
exit(-1);
}
//3>往有名管道里读取数据
char buf[50];
while(1){
bzero(buf,sizeof(buf));
read(fd,buf,sizeof(buf));
printf("%s\n",buf);
}
return 0;
}
3. Read operation:
3. Signal communication
1 Overview:
2. Life cycle:
3. Signal response:
(1) Ignore the signal: No processing is performed on the signal, but there are two signals that cannot be ignored: SIGKILL and SIGSTOP .
(2) Capture the signal: Define the signal processing function. When the signal occurs, execute the corresponding processing function.
(3) Perform default operations: Linux provides default operations for each signal.
4. Signal detection and processing process:
5. Types of signals:
Commonly used signals:
1) SIGHUP ;--->终端在关闭时,给其下所有的进程发送信号 2) SIGINT :--->结束进程 就是:ctrl + c 3) SIGQUIT: --->结束进程 就是:ctrl + \ 9) SIGKILL: --->强制杀死进程 不能被注册,不能被忽略 --->signal 10) SIGUSR1:--->用户自定义信号 --->signal 12) SIGUSR2:--->用户自定义信号 --->signal 14) SIGALRM:-->闹钟信号,用来倒计时,当到0后,触发信号,结束进程 17) SIGCHLD:--->子进程结束时,给父进程发送的信号 18) SIGCONT:--->继续进程 19) SIGSTOP:--->暂停进程: 不能被注册,不能被忽略 --->signal 20) SIGTSTP:-->暂停进程: ctrl + z
6. Send signal:
1>发送信号
kill
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
功能:
发送信号
参数:
pid:接收信号的进程PID:发送给谁
sig:发送的信号是什么
返回值:
成功返回0
失败返回-1,并设置错误码
2>函数转换类型:
atoi --->char型转int型
#include <stdlib.h>
int atoi(const char *nptr);
功能:
将接收到的char型转化为int型
参数:
nptr:接受到的char型
返回值:
成功返回转化后int型
失败返回-1,并设置错误码
从左往右进行转换的
7. Signal processing: signal() function:
信号注册:
signal
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:
信号注册
参数:
signum:需要操作的信号
handler:注册事件
SIG_IGN:忽略
SIG_DFL:默认:恢复
捕捉:注册:执行自己写的一个函数
typedef void (*sighandler_t)(int);--->函数指针
返回值:
成功返回sighandler_t类型
失败返回-1,并设置错误码\
8. Timer function:
pause function, alarm function:
#include <unistd.h>
int pause(void);
功能:
将进程挂起(休眠等待唤醒)--->阻塞
唤醒:捕捉信号,执行该信号则解除挂起-->唤醒
参数:
void
返回值:
成功返回0
失败返回-1,并设置错误码
alarm
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能:
倒计时(计时器)
当倒计时到0时,触发SIGALRM信号,结束进程
参数:
seconds:秒数
返回值:
第一次调用返回0
二次调用以上,返回剩余秒数
9. Test: Code:
When the parent process receives the cltr+c operation, the child process prints: We are going to Wa State to make a fortune.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
//收到信号后执行的函数,通过信号注册传递
void showMsg(int sig){
printf("我们要去佤邦发财啦!\n");
}
//捕捉信号
void sendMsg(int sig){
kill(getppid(),SIGUSR1);
}
int main(){
//因为操作要开出父子进程:fork
pid_t pid=fork();
if(pid>0){
//父进程操作
signal(SIGUSR1,showMsg);
signal(SIGINT,SIG_IGN);
}else if(pid==0){
//子进程的操作
signal(SIGINT,sendMsg);
}
while(1){
//防止过快,显示,也可以用pause()函数
}
return 0;
}