博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux高级编程day07 笔记
阅读量:7093 次
发布时间:2019-06-28

本文共 6971 字,大约阅读时间需要 23 分钟。

回顾:

  1.信号的作用
  2.理解信号:
     软中断
     可靠与不可靠信号kill -l
  3.信号发送与注册kill/raise alarm  setitimer  signal
  4.信号的屏蔽sigprocmask  sigemptyset sigfillset ...
  5.信号屏蔽的切换
      sigpending
      sigsuspend
        =pause+
         指定屏蔽信号
      pause与sigsuspend都回被信号中断.
      中断的是pause与sigsuspen,不是进程中其他代码
      
      sigsuspend放在sigprocmask环境中思考:
      5.1.sigsuspend是否影响sigprocmask屏蔽的信号呢?
         影响.使原来的屏蔽信号全部失效.
         当sigsuspend返回,恢复原来的屏蔽信号.
      5.2.sigsuspend什么时候使用?

View Code
#include 
#include
#include
#include
void handle(int s){ printf("信号干扰!\n");}main(){ int sum=0; int i; sigset_t sigs,sigt; sigemptyset(&sigs); sigemptyset(&sigt); sigaddset(&sigs,SIGINT); //sigfillset(&sigs); signal(SIGINT,handle); sigprocmask(SIG_BLOCK,&sigs,0); for(i=0;i<10;i++) { sum+=i; sleep(5);//模拟业务处理时间比较长 sigsuspend(&sigt); sleep(5); } printf("%d\n",sum); sigprocmask(SIG_UNBLOCK,&sigs,0); printf("over!\n");}
View Code
#include 
#include
#include
#include
void handle(int s){ printf("外部用户中断处理...!\n"); sleep(3); printf("外部用户中断处理完毕!\n");}main(){ int sum=0; int i; sigset_t sigs,sigt,sigu; sigemptyset(&sigs); sigemptyset(&sigt); sigemptyset(&sigu); sigaddset(&sigs,SIGINT); //sigfillset(&sigs); signal(SIGINT,handle); sigprocmask(SIG_BLOCK,&sigs,0); for(i=0;i<10;i++) { printf("正在拷贝电影<%d>!\n",i); sleep(5);//模拟业务处理时间比较长 printf("正在拷贝电影<%d>完毕!\n",i); sigpending(&sigu); if(sigismember(&sigu,SIGINT)) { sigsuspend(&sigt); } } printf("所有电影拷贝完毕\n",sum); sigprocmask(SIG_UNBLOCK,&sigs,0); printf("over!\n");}

一.最新版本的信号发送与处理

  sigqueue/sigaction          
1.思考:信号中断函数调用中是否被其他信号中断.          
  信号函数调用中只屏蔽本身信号,不屏蔽其他信号.
2.怎么保证函数调用中屏蔽指定的信号呢?
  sigaction可以指定处理函数调用的屏蔽信号
  sigaction在处理信号的时候,接受数据.
  
  sigqueue发送信号的时候,可以发送数据.
  
  sigaction/sigqueue是signal/kill的增强版本

View Code
#include 
#include
#include
main(){ union sigval val; val.sival_int=8888; sigqueue(3972,SIGUSR1,val);}

3.函数说明     

  使用sigaction/sigqueue有两个理由.
  3.1.稳定
  3.2.增强功能

int sigaction(        int sig,//被处理信号        const struct sigaction*action,//处理函数及其参数        struct sigaction*oldact//返回原来的处理函数结构体        )

 返回:

   0:成功
   -1:失败

struct sigaction    {        void (*sa_handle)(int);        void (*sa_sigaction)(int,siginfo_t*,void*);        sigset_t *mask;//屏蔽信号        int flags;//SA_SIGINFO        void**//保留成员.    }
View Code
#include 
#include
#include
/*void handle(int s){ printf("OOOK!\n"); sleep(5); printf("K000!\n");}*/void handle(int s,siginfo_t* info,void *d){ printf("OOOK:%d\n",info->si_int); sleep(5); printf("K000!\n");}main(){ struct sigaction act={
0}; //act.sa_handler=handle; act.sa_sigaction=handle; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask,SIGINT); act.sa_flags=SA_SIGINFO; sigaction(SIGUSR1,&act,0); while(1); }

案例:

   1.使用sigaction处理信号,使用kill发送信号
   2.使用sigaction处理信号,使用sigqueue发送信号
   3.发送信号的同时处理数据   
二.IPC
  1.基于文件
    1.1.无序文件
    1.1.有序文件
      1.1.1.管道
        1.1.1.1.有名
        1.1.1.2.匿名
      1.1.2.socket
  2.基于内存
    2.1.无序内存
      2.1.1.匿名内存
      2.1.2.共享内存
    2.2.有序内存
      2.2.1.共享队列
  3.同步:基于内存IPC应用(共享内存数组)
    信号量/信号灯
    
三.基于普通文件的IPC
  IPC的技术提出的应用背景.
  进程之间需要同步处理:
  同步需要通信.
  普通文件就是最基本的通信手段.

View Code
#include 
#include
#include
main(){ int *p; int fd; int i; fd=open("tmp",O_RDWR|O_CREAT,0666); ftruncate(fd,4); p=mmap(0,4,PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); i=0; while(1) { sleep(1); *p=i; i++; } close(fd);}
View Code
#include 
#include
#include
main(){ int *p; int fd; fd=open("tmp",O_RDWR); p=mmap(0,4,PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); while(1) { sleep(1); printf("%d\n",*p); } close(fd);}

  普通文件IPC技术的问题:

    一个进程改变文件,另外一个进程无法感知.
  解决方案:
     一个特殊的文件:管道文件

四.管道文件

  1.创建管道mkfifo
  2.体会管道文件特点
 案例:        
   fifoA       fifoB
   建立管道      
   打开管道   打开管道
   写数据    读数据
   关闭管道   关闭管道
   删除管道
    
 建立管道文件:
   使用linux的指令mkfifo

View Code
#include 
#include
#include
#include
#include
#include
int fd;int i;void end(int s){ //关闭管道 close(fd); //删除管道 unlink("my.pipe"); exit(-1);} main(){ signal(SIGINT,end); //建立管道 mkfifo("my.pipe",0666); //打开管道 fd=open("my.pipe",O_RDWR); //shutdown(fd,SHUT_RD); i=0; while(1) { //每隔1秒写数据 sleep(1); write(fd,&i,4); i++; } }
View Code
#include 
#include
#include
#include
#include
#include
int fd;void end(int s){ //关闭管道 close(fd); exit(-1);}main(){ int i; //打开管道 signal(SIGINT,end); fd=open("my.pipe",O_RDWR); //shutdown(fd,SHUT_WR); while(1) { read(fd,&i,4); printf("%d\n",i); } }

 总结:

   1.read没有数据read阻塞,而且read后数据是被删除
   2.数据有序
   3.打开的描述符号可以读写(two-way双工)
   4.管道文件关闭后,数据不持久.
   5.管道的数据存储在内核缓冲中.
五.匿名管道
  发现有名的管道的名字仅仅是内核识别是否返回同一个fd的标示.
  所以当管道名失去表示作用的时候,实际可以不要名字.
     
  在父子进程之间:打开文件描述后创建进程.
  父子进程都有描述符号. 管道文件没有价值.
  所以在父子进程中引入一个没有名字的管道:匿名管道.
  结论:
    匿名管道只能使用在父子进程.

View Code
#include 
#include
#include
main(){ int fd[2]; pipe(fd); if(fork()) {
//parent close(fd[0]);//只负责写 while(1) { write(fd[1],"Hello",5); sleep(1); } } else {
//child char buf[20]; int r; close(fd[1]);//只负责读 while(1) { r=read(fd[0],buf,20); buf[r]=0; printf("::%s\n",buf); } }}

  1.创建匿名管道

  2.使用匿名管道
案例:
  匿名管道的创建
  体会匿名管道的特点
  int pipe(int fd[2]);//创建管道.打开管道.拷贝管道.关闭读写  
  fd[0]:只读(不能写)
  fd[1]:只写(不能读) 
  
  注意:数据无边界.
  
综合:
  建立两个子进程:
   一个负责计算1-5000的素数
   另外一个负责计算5001-10000
   父进程负责存储

View Code
#include 
#include
#include
#include
#include
#include
#include
int idx=0;int fddata;void handle(int s){ int status; if(s==SIGCHLD) { wait(&status); idx++; if(idx==2) { close(fddata); printf("任务完成\n"); exit(-1); } }}int isprimer(int ta){ int i=2; for(;i
2){ break; } continue; } else{ //子进程 int i; close(fd[0]); for(i=a;i<=b;i++) { if(isprimer(i)) { write(fd[1],&i,sizeof(int)); } sched_yield(); } printf("%d任务完成!\n",getpid()); exit(0); } } int re; char buf[20]; //打开文件,准备存储 close(fd[1]); fddata=open("result.txt", O_RDWR|O_CREAT,0666); while(1) { read(fd[0],&re,sizeof(int)); sprintf(buf,"%d\n",re); write(fddata,buf,strlen(buf)); sched_yield(); } }

 

转载于:https://www.cnblogs.com/tangzhengyue/archive/2012/08/22/2650313.html

你可能感兴趣的文章
在XenServer 6.0中设置自动启动虚拟机
查看>>
【大数据培训】大数据带你寻找“惊心动魄”
查看>>
centos7修改网卡一致性命名
查看>>
文件管理命令及变量基础
查看>>
find
查看>>
如何理解磁力
查看>>
安卓学习-NDK开发
查看>>
Linux的基础学习
查看>>
MyBatis--01.基础
查看>>
JEESZ-Redis分布式缓存安装和使用
查看>>
for和each的区别
查看>>
为什么我这样做会出错,求教
查看>>
【Java多线程】的学习总结
查看>>
五分钟搭建你的第一个区块链应用
查看>>
家庭WiFi有限的访问权限
查看>>
自动化运维之 部署Saltstack 并批量部署 Nginx
查看>>
Linux常用中间件启动命令
查看>>
中文自动摘要的基本实现方法
查看>>
如何使Windows显示文件扩展名
查看>>
springmvc拦截器讲解
查看>>