加入收藏 | 设为首页 | 会员中心 | 我要投稿 我爱资讯网 (https://www.52junxun.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

D3 - Unix进程间通信方式

发布时间:2022-10-19 12:46:09 所属栏目:Unix 来源:
导读:  第一节linux中进程间通信的方式pipe(无名管道)

  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
 
  接受到信号,进程被唤醒。
 
 

(编辑:我爱资讯网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章