D3 - Unix进程间通信方式
发布时间:2022-10-19 12:46:09 所属栏目:Unix 来源:
导读: 第一节linux中进程间通信的方式pipe(无名管道)
fifo有名管道
signal (信号)
System V IPC
socket 套接字(网络通信)
1.1无名管道pipe
无名管道pipe
uni
fifo有名管道
signal (信号)
System V IPC
socket 套接字(网络通信)
1.1无名管道pipe
无名管道pipe
uni
|
第一节linux中进程间通信的方式pipe(无名管道) fifo有名管道 signal (信号) System V IPC socket 套接字(网络通信) 1.1无名管道pipe 无名管道pipe unix进程通信_易语言驱动全通信源码,驱动级进程隐藏,进程保护_进程到进程之间的通信 ) 特点:1:只能用于父子/祖孙/兄弟进程(两个子进程)这类亲缘关系的进程间通信 2:无名管道有读端与写端,需要两个进程一个接入到读端,一个接入到写段 3:无名管道被创建时会返回两个文件描述符,也就是两个文件,分别对应的就是我们的无名管道的读端与写端 1.1.1无名管道的创建 pipe函数 功能: 1:在父进程中创建子进程1和子进程2 2:进程1向管道1发送hello word,进程2从管道1取出hello word 3:进程2向管道2发送HELLO WORD,进程1从管道2取出HELLO WORD 注意: 管道创建后,不是指定必须连接哪两个进程, 任意的亲戚进程都直接操作两个文件描述符就是接入了管道, 哪个进程操作文件描述符就是连接无名管道 11 ================================================================*/ 12 #include 13 #include 14 #include 15 #include 16 #include 17 18 void main() 19 { 20 char str1[32] = "hello word"; 21 char str2[32] = "HELLO WORD"; 22 23 创建两个pid进程号 24 pid_t pid1; 25 pid_t pid2; 26 27 28 创建2个数组来接受2个管道的‘文件标示符’ 29 int array1[2]; 30 int array2[2]; 31 32 创建无名管道1 33 if(EOF==pipe(array1)) 34 { 35 perror("\n管道1创建失败\n"); 36 } 37 else 38 { 39 printf("\n管道1创建成功\n"); 40 } 41 42 创建无名管道2 43 if(EOF==pipe(array2)) 44 { 45 perror("\n管道2创建失败\n"); 46 } 47 else 48 { 49 printf("\n管道2创建成功\n"); 50 } 51 52 创建2个子进程 53 pid1 = fork(); 54 pid2 = fork(); 55 56 判断父进程 57 if(pid1 >0 && pid2 >0) 58 { 59 printf("\nmain父进程"); 60 61 父进程进入等待 62 while(1) 63 { 64 65 } 66 } 67 68 判断子进程1 69 else if(pid1 == 0 && pid2>0) 70 { 71 char pid1_getstr[32] = {0}; 72 printf(" \n进入进程1\n"); 73 while(1) 74 { 75 向管道1写数据 76 write(array1[1],str1,32); 77 printf("\n进程1+管道1>>写入hello word\n"); 78 79 从管道2读数据 80 read(array2[0],pid1_getstr,32); 81 printf("\n进程1+管道2>>读取到%s\n",pid1_getstr); 82 sleep(2); 83 } 84 } 85 判断子进程2 86 else if(pid1>0 && pid2 ==0) 87 { 88 char pid2_getstr[32] = {0};//pid2进程接受管道数据 89 printf("\n进入进程2\n"); 90 while(1) 91 { 92 93 从管道1读数据 94 read(array1[0],pid2_getstr,32); 95 printf("\n进程2+管道1>>读取到%s\n",pid2_getstr); 96 97 向管道2写数据 98 write(array2[1],str2,32); 99 printf("\n进程2+管道2>>写入HELLO WORD\n"); 100 101 sleep(2); 102 } 103 } 104 105 } ================================================================*/ 结果:两个子进程通过两个无名管道实现进程间的数据传输 farsight@ubuntu:~/Desktop$ ./a.out 管道1连接成功 管道2连接成功 进入进程1 进程1+管道1>>写入hello word 进入进程2 进程2+管道1>>读取到hello word 进程1+管道2>>读取到HELLO WORD 进程2+管道2>>写入HELLO WORD 进程1+管道1>>写入hello word 进程2+管道1>>读取到hello word 进程1+管道2>>读取到HELLO WORD 进程2+管道2>>写入HELLO WORD 进程1+管道1>>写入hello word 进程2+管道1>>读取到hello word 进程1+管道2>>读取到HELLO WORD 第二讲有名管道与无名管道的差别是,无名管道虽然有文件描述符但是没有实际文件,而有名管道有实际的文件 一个有名管道便可实现两个进程的数据交互 ## 2.1 创建有名管道 mkfifo函数 int mkfifo(const char *path, mode t mode); path:管道文件的路径 mode:代表管道文件的权限unix进程通信,如0666 通过有名管道实现两个父进程之间的通信 11 ==============================text1.c==================================*/ 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include 18 #include 19 #include 20 21 void main() 22 { 23 建立有名管道,创建有名管道文件(该文件不是普通文件,只能用open打开) 24 if(EOF==mkfifo("/home/farsight/Desktop/myfifo",0666)) 25 { 26 perror("\nmkfifo error:\n"); 27 } 28 else 29 { 30 printf("\n mkfifo ok \n"); 31 } 32 33 因为管道文件不是普通文件,不能用fopen打开,只能用open 34 int pfd; 文件描述符 35 36 char str[32]={0}; 37 38 打开管道文件 39 pfd=open("/home/farsight/Desktop/myfifo",O_WRONLY); 40 41 if(pfd <0 ) 42 { 43 perror("\n打开文件失败\n"); 44 } 45 else 46 { 47 printf("\n打开文件成功\n"); 48 } 49 50 while(1) 51 { 52 写入管道文件 53 write(pfd,"hello man",32); 54 55 printf("\n向无名管道写入hello man\n"); 56 57 sleep(2); 58 59 读取管道文件 60 read(pfd,str,32); 61 62 printf("\n从有名管道读出%s\n",str); 63 } 64 } 11 ====================================text2.c============================*/ 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include 18 19 void main() 20 { 21 22 int pfd; 文件描述符 23 24 char str[32] = {0}; 25 26 打开有名管道文件 27 pfd=open("/home/farsight/Desktop/myfifo",O_RDONLY); 28 29 if(pfd <0 ) 30 { 31 perror("\n打开文件失败\n"); 32 } 33 else 34 { 35 printf("\n打开文件成功\n"); 36 } 37 38 while(1) 39 { 40 读管道文件 41 read(pfd,str,32); 42 printf("\n从有名管道读出%s\n",str); 43 sleep(2); 44 45 写管道文件 46 write(pfd,"HELLO WORD",32); 47 printf("\n向有名管道写入HELLO WORD\n"); 48 } 49 } ====================================结果============================*/ 进程1: farsight@ubuntu:~/Desktop$ ./text1 mkfifo ok 打开文件成功 向有名管道写入hello man 向有名管道写入hello man 向有名管道写入hello man 向有名管道写入hello man 向有名管道写入hello man 向有名管道写入hello man 向有名管道写入hello man 向有名管道写入hello man 进程2: farsight@ubuntu:~/Desktop$ ./text2 打开文件成功 从有名管道读出hello man 从有名管道读出hello man 从有名管道读出hello man 从有名管道读出hello man 从有名管道读出hello man 从有名管道读出hello man 从有名管道读出hello man 从有名管道读出hello man >>结果:text1.c与text2.c这两个父进程实现进程间的有名管道的通信! 第三讲 (信号机制了解)信号机制==中断机制信号是对中断机制的软件模拟 与硬件中断类似,当程序接收到信号后,程序会暂停执行,转去响应信号,然后再继续执行程序 不同的信号代表不同的事件 == 不同的中断信号代表不同的中断事件 linux有64种信号(类似于中断信号);使用kill -l 查看信号类型 易语言驱动全通信源码,驱动级进程隐藏,进程保护_进程到进程之间的通信_unix进程通信 信号的处理方式 缺省方式(默认中断处理方式) 忽略该信号 捕捉信号(用户中断处理函数) 所有常见到的信号 SIGNUP--中断关闭时触发--进程终止 SIGINT--ctrl+c触发该信号--终止进程(为什么ctrl+c能关闭进程的原因) SIGQUIT--ctrl+\触发该信号--终止进程(与ctrl+c效果一致) SIGILL--执行了非法指令时触发--终止进程 SIGSEV--内存溢出,野指针时触发--终止进程(经常看见段错误后,进程就强制退出的原因) SIGPIPE--写入管道错误触发--终止进程 SIGKILL--用来关闭进程(进程被关闭的原因) SIGSTOP--暂停进程(gdb调试能设置断点暂停进程的原因) SIGTSTP--ctrl+z--暂停进程 SIGCONT--继续运行进程(GDB调试,能继续运行程序的原因) SIGALRM--定时器信号;定时器时间到了后会让进程结束 SIGUSR1/2--用户可以使用的两个信号 信号相关命令 kill 对当前终端的进程发送信号 使用举例: 进程到进程之间的通信_unix进程通信_易语言驱动全通信源码,驱动级进程隐藏,进程保护 killall对所有终端的进程发送信号 使用举例: 易语言驱动全通信源码,驱动级进程隐藏,进程保护_进程到进程之间的通信_unix进程通信 第四讲4.1 发送信号 kill函数 int kill(pid t pid, int sig); 1:成功返回0,失败返回EOF 2:pid=进程号 3:sig=信号类型 功能:使用kill函数,向当前进程发送信号指令 11 ================================================================*/ 22 void main() 23 { 24 int mypid; 25 26 mypid = getpid(); 获取当前进程的进程号 27 28 kill(mypid,2); 向当前进程发生信号2,关闭进程的指令,可以通过kill -l 创建信号 29 30 printf("发生(ctrl+c)指令2失败"); 如果运行到这一步,说明进程没有关闭,指令kill发生失败! 31 32 } 结果:成功接收到ctrl+c的信号2 farsight@ubuntu:~/Desktop$ ./text1 farsight@ubuntu:~/Desktop$ 4.2 创建闹钟/定时器 alarm函数 int alarm(unsigned int seconds);1:创建闹钟时,原来的闹钟的值会被返回记录下来,这个值就是alarm的返回值 2:seconds=闹钟时间(单位为s) ; seconds设定为0,表示定时0,表示关闭当前闹钟 3:闹钟时间一到,内核会向该进程发送闹钟信号SIGALRM,将进程关闭,利用该机制alarm一般用来实现超时检测的功能 功能:如果程序运行时间超过5s就触发闹钟信号,将程序强行关闭 ================================================================*/ 22 void main() 23 { 24 25 alarm(5); 闹钟定时5s 26 27 int i=0; 28 while(1) 死循环打印程序程序的时间 29 { 30 sleep(1); 31 i=i+1; 32 printf("\n>>运行时间:%d\n",i); 33 } 34 35 } 结果: farsight@ubuntu:~/Desktop$ ./text1 >>运行时间:1 >>运行时间:2 >>运行时间:3 >>运行时间:4 闹钟 //最后的"闹钟"是闹钟信号触发的中断函数的输出结果 4.3 进程睡眠pause函数 int pause ( void); 1:该函数让进程进入阻塞睡眠的停止态,当有进程接收到信号后唤醒进程继续执行 2:接收到信号中断.返回-1 4.4设置信号的响应方式 signal函数 void (signal(int signo, void (handler)(int)))(int);1:将信号与信号处理函数关联起来 2:signo=要设置的信号类型 3:handler=函数指针 SIG_DEL=缺省方式/默认方式;SIG_IGN=忽略信号; 成功时返回原先的信号处理函数,失败时返回 SIG ERR 利用signal函数与pause函数实现用户信号绑定同一个信号相应函数 11 ================================================================*/ 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include 18 #include 19 #include 20 #include 21 22 //这个函数的的书写形式可以参考man 23 void handler(int send) 24 { 25 //信号判断 26 if(send == SIGUSR1) 27 { 28 printf("\nhello word\n"); 29 } 30 else if(send == SIGUSR2) 31 { 32 printf("\nHELLO WORD\n"); 33 } 34 } 35 36 void main() 37 { 38 //一直睡,等待信号唤醒 39 40 signal(SIGUSR1,handler);//将SIGUSR1信号与handler函数关联 41 signal(SIGUSR2,handler);//将SIGUSR2信号与handler函数关联 42 43 44 while(1) 45 { 46 pause(); 47 printf("\n接受到信号,进程被唤醒\n"); 48 } 49 } ================================================================*/ 结果验证: 在中断1种向text1进程发送10,12号信号 farsight@ubuntu:~/Desktop$ killall -12 text1 farsight@ubuntu:~/Desktop$ killall -10 text1 进程调试结果:成功! 在信号触发后,优先运行信号处理函数handler, 根据不同信号打印大小写hello word, 处理函数结束后,pause函数将进程唤醒 farsight@ubuntu:~/Desktop$ ./text1 HELLO WORD 接受到信号,进程被唤醒 hello word 接受到信号,进程被唤醒。 (编辑:我爱资讯网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
