学习 Linux高级编程07_A

回顾:

         1.信号的作用

         2.理解信号:

                   软中断

                   可靠与不可靠 kill-l

         3.信号发送与注册kill/raise alarm setitimer signal

         4.信号的屏蔽sigprocmask sigemptyset sigfillset

         5.信号屏蔽切换

                   sigpending

                   sigsuspend

                            =pause + 指定屏蔽的信号

                   pausesigsuspend都会被信号中断

                   中断的是pausesigsuspend,不是进程中其他代码

                  

                   sigsuspend放在sigprocmask环境中思考:

                            5.1sigsuspend是否影响sigprocmask屏蔽的信号呢?

                                     影响,使原来屏蔽信号全部失效

                                     sigsuspend返回,恢复原来的屏蔽信号

                            5.2sigsuspend什么时候使用?

 

一、最新版本的发送与处理

         sigqueue/sigaction

1.思考:

         信号中断函数调用中是否被其他信号中断。

         信号函数调用中只屏蔽本身信号,不屏蔽其他信号

2.怎么保证函数调用中屏蔽指定的信号呢?

         sigaction可以指定处理函数调用的屏蔽信号

         sigaction在处理信号的时候,接收数据。

         sigqueue发送信号的时候,可以发送数据

         sigaction/sigqueuesignal/kill的增强版本

3.函数说明

         使用sigaction/sigqueue有两个理由。

         3.1稳定

         3.2增强功能

         intsigaction(

         intsig, //被处理信号

         conststruct sigaction *action, //处理函数及其参数

         structsigaction *oldact //返回原来的处理函数结构体

         )

         返回值:

                   0:成功

                   -1:失败

         structsigaction

         {

                   void(*sa_handle)(int);

                   void(*sa_sigaction)(int, siginfo_t*, void*);

                   sigset_t*mask; //屏蔽信号

                   intflags; //SA_SIGINFO

                   void** //保留成员

         }

案例:

         1.使用sigaction处理信号,使用kill发送信号

         2.使用sigaction处理信号,使用sigqueue发送信号

         3.发送信号的同时处理数据。

二、IPC

         1.基于文件

                   1.1无序文件

                   1.2有序文件

                            1.1.1管道

                                     1.1.1.1有名

                                     1.1.1.2匿名

                            1.1.2socket

         2.基于内存

                   2.1无序内存

                            2.1.1匿名内存

                            2.1.2共享内存

                   2.2有序内存

                            2.2.1共享队列

         3.同步:基于内存IPC应用(共享内存数组)

                   信号量/信号灯

三、基于普通文件的IPC

                   IPC的技术提出的应用背景

                   进程之间需要同步处理:

                   同步需要通信

                   普通文件就是最基本的通信手段。

                   普通文件IPC技术问题:

                            一个进程改变文件,另外一个进程无法感知

                   解决方案:

                            一个特殊的文件:管道文件

四、管道文件

         1.创建管道文件mkfifo()

         2.体会管道文件特点

案例:

         fifoA          fifoB

         建立管道        

         打开管道         打开管道

         写数据              度数据

         关闭管道         关闭管道

         删除管道

        

         建立管道文件方法:

                   使用Linux的指令mkfifo

总结:

         1.read没有数据read阻塞,而且read后数据是被删除

         2.数据有序

         3.打开的描述符号可以读写(two-way双工)

         4.管道文件关闭后,数据不持久。

         5.管道的数据存储在内核缓冲中。

                  

五、匿名管道

                   发现有名的管道的名字紧紧是内核识别是否返回同一个fd(文件描述符)的标识

                   所以当管道名失去表示作用的时候,实际可以不要

                   在父子进程之间:打开文件描述符后创建进程。

                   父子进程都有描述符。管道名没有价值。

                   所以在父子进程中引入一个没有名字的管道:匿名管道

结论:

         匿名管道只能使用在父子进程。

         1.创建匿名管道

         2.使用匿名管道

案例:

         匿名管道的创建

         体会匿名管道的特点

         intpipe(int fd[2]); //创建一个管道打开管道拷贝管道关闭读写

         fd[0]:只读(不能写)

         fd[1]:只写(不能读)

         注意:数据无边界。

综合:

         建立两个子进程:

         一个负责计算1-5000的素数

         另外一个负责计算5001-10000的素数

         父进程负责存储

 

 

 

Sigmask.c

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

main()

{

         int  sum = 0;

         int  i;

         for(i  = 0; i < 10; i ++)

         {

                   sum  += i;

                   sleep(1);  //模拟业务处理时间比较长

         }

         printf("%d\n",  sum);

         printf("over\n"):

}

makefile

sigmask:

         gcc  sigmask.c -o sigmask

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

void handle(int s)

{

         printf("signal  disturb!!\n");

}

 

main()

{

         int  sum = 0;

         int  i;

         signal(SIGINT,  handle);

         for(i  = 0; i < 10; i ++)

         {

                   sum  += i;

                   sleep(1);  //模拟业务处理时间比较长

         }

         printf("%d\n",  sum);

         printf("over\n"):

}

上面for循环中,随时可能中断。

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

void handle(int s)

{

         printf("signal  disturb!!\n");

}

 

main()

{

         int  sum = 0;

         int  i;

                  

         sigset_t  sigs; //屏蔽步骤1 定义信号集

         sigemptyset(&sigs);  //屏蔽步骤2 清空信号集

         sigaddset(&sigs,  SIGINT); //屏蔽步骤3 添加被屏蔽的信号

 

         signal(SIGINT,  handle);

         sigprocmask(SIG_BLOCK,  &sigs, 0);//屏蔽步骤4 添加被屏蔽的代码块开始

         for(i  = 0; i < 10; i ++)

         {

                   sum  += i;

                   sleep(1);  //模拟业务处理时间比较长

         }

         printf("%d\n",  sum);

         sigprocmask(SIG_UNBLOCK,  &sigs, 0);//屏蔽步骤4 添加被屏蔽的代码块结束

         printf("over\n"):

}

在程序执行过程中多次的信号被压缩为一次

 

Suspend.c

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

void handle(int s)

{

         printf("signal  disturb!!\n");

}

 

main()

{

         sigset_t  sigs;

         sigemptyset(&sigs);

        

         signal(SIGUSR1,  handle);

        

         sigsuspend(&sigs);  //挂起

         printf("over\n"):

}

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

main()

{

         sigset_t  sigs;

         sigemptyset(&sigs);

 

         sigsuspend(&sigs);  //挂起

         printf("over\n"):

}

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

main()

{

         pause();

         printf("over\n"):

}

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

void handle(int s)

{

         printf("signal  disturb!!\n");

}

 

main()

{

         sigset_t  sigs;

         sigemptyset(&sigs);

         sigaddset(&sigs,  2);

         sigaddset(&sigs,  10);

         signal(SIGUSR2,  handle);

        

         sigsuspend(&sigs);  //挂起

         printf("over\n"):

}

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

void handle(int s)

{

         printf("signal  disturb!!\n");

}

 

main()

{

         int  sum = 0;

         int  i;

                  

         sigset_t  sigs, sigt;

         sigemptyset(&sigs);

         sigemptyset(&sigt);

         sigaddset(&sigs,  SIGINT);

        

         signal(SIGINT,  handle);

         sigprocmask(SIG_BLOCK,  &sigs, 0);

         for(i  = 0; i < 10; i ++)

         {

                   sum  += i;

                   sleep(1); 

                   sigsuspend(&sigt);

         }

         printf("%d\n",  sum);

         sigprocmask(SIG_UNBLOCK,  &sigs, 0);

         printf("over\n"):

}

Demo41.c

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

void handle(int s)

{

         printf("out  copy over !\n");

}

 

main()

{

         int  sum = 0;

         int  i;

                  

         sigset_t  sigs, sigt;

         sigemptyset(&sigs);

         sigemptyset(&sigt);

         sigaddset(&sigs,  SIGINT);

        

         signal(SIGINT,  handle);

        

         for(i  = 0; i < 10; i ++) //可能中断,导致刚要指向就中断

         {

                   sigprocmask(SIG_BLOCK,  &sigs, 0); //存在漏洞

                   sum  += i;

                   printf("copy  start\n");

                   sleep(5);

                   sigprocmask(SIG_UNBLOCK,  &sigs, 0);

                   printf("copy  over\n")

                   sigsuspend(&sigt);

         }

         printf("%d\n",  sum);

        

         printf("over\n"):

}

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<unistd.h>

 

void handle(int s)

{

         printf("out  disturb start!\n");

         sleep(3);

         printf("out  disturb end!\n");

}

 

main()

{

         int  i;

                  

         sigset_t  sigs, sigt,sigu;

         sigemptyset(&sigs);

         sigemptyset(&sigt);

         sigemptyset(&sigu);

         sigaddset(&sigs,  SIGINT);

        

         signal(SIGINT,  handle);

         sigprocmask(SIG_BLOCK,  &sigs, 0)

         for(i  = 0; i < 10; i ++)

         {

                   printf("copy  start %d\n", i);

                   sleep(5);

                   printf("copy  end %d\n", i)

                   sigpending(&sigu);

                   if(sigismember(&sigu,  SIGINT))

                   {

                            sigsuspend(&sigt);

                   }

 

         }

         printf("all  copy over", sum);

         sigprocmask(SIG_UNBLOCK,  &sigs, 0)

         printf("over\n"):

}

你可能感兴趣的:(学习 Linux高级编程07_A)