zoukankan      html  css  js  c++  java
  • linux高级编程day07 笔记

    回顾:
      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 <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    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 <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    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 <stdio.h>
    #include <signal.h>
    #include <unistd.h>
    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 <stdio.h>
    #include <signal.h>
    
    #include <unistd.h>
    /*
    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 <stdio.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    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 <stdio.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    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 <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <signal.h>
    #include <stdlib.h>
    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 <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <signal.h>
    #include <stdlib.h>
    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 <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    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 <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sched.h>
    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<ta;i++)
        {
            if(ta%i==0)
            {
                return 0;
            }
        }
        return 1;
    }
    main()
    {
        int a,b;
        int id=1;
        int fd[2];
        signal(SIGCHLD,handle);
        pipe(fd);
        while(1)
        {
            if(id==1){
                a=2;b=50000;
            }
            if(id==2){
                a=50001;b=100000;
            }
            if(fork()){            
                id++;
                if(id>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();
        }
        
    }        
  • 相关阅读:
    User Profile Service 应用程序的新增功能
    内容管理互操作性服务 (CMIS) 连接器概述 (SharePoint Server 2010)
    AD二次开发提示“出现了一个操作错误”的解决办法
    Excel2010与MOSS2010数据同步配置
    InfoPath2010表单IE浏览器2个“微型内嵌工具”的使用和介绍
    洗礼灵魂,修炼python(1)python简介
    洗礼灵魂,修炼python(2)python安装和配置
    C语言标准定义的32个关键字
    【学习笔记】.NET知识体系结构
    【读】自定义博客园皮肤:暗色流体响应式布局
  • 原文地址:https://www.cnblogs.com/tangzhengyue/p/2650313.html
Copyright © 2011-2022 走看看