linux进程间通信异步信号处理机制

Posted Henry Zheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux进程间通信异步信号处理机制相关的知识,希望对你有一定的参考价值。

linux实验报告9、10章

 

第九章 进程间通信(管道)

实验9-4

实现一个服务器和多个客户端之间的通信:

(1)服务器创建一个有名管道,供客户端写入信息.

(2)每个客户端为自己创建有名管道.供服务器写入信息.

(3)客户端打印出发送到服务器的信息,从服务器接受到的信息

 

题目分析:

使用MUFIFO作为命题管道,使用fopen函数打开对应的命名管道,然后将argv中的字符串写入该命名管道中.创建fifosend.c

与之前相类似,使用fopen函数打开命名为MYFIFO的管道文件,然后从其中读出对应的字符串并显示在屏幕上.创建fifoget.c

 

实验结果:

 

实验代码:

//fifosend.c

 

#include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

 

#define FIFO_FILE "MYFIFO"

 

int main(int argc, char *argv[])

        FILE *fp;

        int i;

        if(argc<2)

        

                printf("please use :%s<pathname>\\n", argv[0]);

                exit(1);

        

        if((fp=fopen(FIFO_FILE,"w")) == NULL)

        

                printf("fopen error!\\n");

                exit(1);

        

        for(i=1;i<argc;i++)

        

                if(fputs(argv[i],fp) == EOF)

                

                        printf("write fifo error!\\n");

                        exit(1);

                

                if(fputs("",fp) == EOF)

                

                        printf("write fifo error!\\n");

                        exit(1);

                

        

        fclose(fp);

        return 0;

                                                                                                                                                                                       

 

//fifoget.c

 

#include<stdio.h>

#include<stdlib.h>

#include<sys/stat.h>

#include<unistd.h>

#include<linux/stat.h>

#include<errno.h>

 

#define FIFO_FILE "MYFIFO"

 

int main(int argc, char argv[])

        FILE *fp;

        char readbuf[80];

 

        if((fp=fopen(FIFO_FILE, "r")) == NULL)

        

                umask(0);

                mknod(FIFO_FILE,S_IFIFO|0666,0);

        

        else

        

                fclose(fp);

        

        while(1)

        

                if((fp=fopen(FIFO_FILE, "r")) == NULL)

                

                        printf("open fifo error!\\n");

                        exit(1);

                

                if(fgets(readbuf, 80, fp)!=NULL)

                

                        printf("get the readbuf is : %s\\n", readbuf);

                        fclose(fp);

                

                else

                

                        if(ferror(fp))

                        

                                perror("read file error!\\n");

                                exit(1);

                        

                

        

        return 0;

 

 

 

 

 

第十章 异步信号处理机制

实验10-1

编写程序测试函数setitimer(int)和getitimer()。

安装信号, 使信号SIGALRM、SIGVTALRM、SIGPROF可以被捕获。

测试:setitimer()函数

运行结果:

 

实验代码:

//setitimer.c

 

#include<stdlib.h>

 

static void signalDeal(int signo)

        struct timeval tp;

        struct tm *tm;

        gettimeofday(&tp,NULL);

        tm=localtime(&tp.tv_sec);

        system("clear");

        printf("sec=%d\\t",tp.tv_sec);

        printf("usec=%d\\n",tp.tv_usec);

        printf("%d-%d-%d  %d:%d:%d\\n",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);

 

static void InitTime(int tv_sec,int tv_usec)

        struct itimerval value;

        signal(SIGALRM,signalDeal);

        value.it_value.tv_sec=tv_sec;

        value.it_value.tv_usec=tv_usec;

        value.it_interval.tv_sec=tv_sec;

        value.it_interval.tv_usec=tv_usec;

        setitimer(ITIMER_REAL,&value,NULL);

 

int main(int argc,char *argv[])

        InitTime(1,0);

        while(1)

        

        

        exit(0);

实验10-2

编写程序测试sigaction()函数。

sa_flags 设置为以下标志时,程序的行为有何不同。

对比程序运行情况予以说明。

SA_SIGINFO

SA_NOCLDSTOP

SA_NOCLDWAIT

SA_NODEFER

SA_RESETHAND

 

测试sigaction()函数

运行结果:

 

 

测试sigaction2()函数

运行结果:

 

函数代码:

//sigaction.c

 

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

 

void signalDeal(int sig,siginfo_t*info,void *t)

        if(sig==SIGINT) //CTRL+C

        

                printf("使用CTRL+C!\\n");

        

        else if(sig==SIGQUIT) //CTRL+/

        

                printf("使用CTRL+/!\\n");

        

        else

        

                printf("其他信号!\\n");

        

 

int main(int argc,char *argv[])

        struct sigaction act;

        act.sa_sigaction = signalDeal;

        sigemptyset(&act.sa_mask);

        act.sa_flags=SA_SIGINFO;

        sigaction(SIGINT,&act,NULL);

        sigaction(SIGQUIT,&act,NULL);

        while(1)

        

        

        return 0;

 

//sigaction2.c

 

#include <stdio.h>

#include <unistd.h>

#include <signal.h>

#include <errno.h>

 

static void sig_usr(int signum)

    if(signum == SIGUSR1)

    

        printf("SIGUSR1 received\\n");

    

    else if(signum == SIGUSR2)

    

        printf("SIGUSR2 received\\n");

    

    else

    

        printf("signal %d received\\n", signum);

    

 

int main(void)

    char buf[512];

    int  n;

    struct sigaction sa_usr;

    sa_usr.sa_flags = 0;

    sa_usr.sa_handler = sig_usr;   //信号处理函数

    sigaction(SIGUSR1, &sa_usr, NULL);

    sigaction(SIGUSR2, &sa_usr, NULL);

    printf("My PID is %d\\n", getpid());

    while(1)

    

        if((n = read(STDIN_FILENO, buf, 511)) == -1)

        

            if(errno == EINTR)

            

                printf("read is interrupted by signal\\n");

            

        

        else

        

            buf[n] = '\\0';

            printf("%d bytes read: %s\\n", n, buf);

        

    

    return 0;

 

 

 

测试sigprocmask()函数

运行结果:

 

 

 

实验代码:

//sigprocmask.c

 

#include <stdio.h>

#include <unistd.h>

#include <signal.h>

#include <stdlib.h>

 

static void sig_quit(int signo)

        printf("caught SIGQUIT\\n");

        signal(SIGQUIT, SIG_DFL);//再次安装

int main()

        sigset_t newmask, oldmask, pendmask;

 

        signal(SIGQUIT, sig_quit);//安装信号处理函数

 

        sigemptyset(&newmask);//初始化信号量集

        sigaddset(&newmask, SIGQUIT);//将SIGQUIT添加到信号量集中

 

        sigprocmask(SIG_BLOCK, &newmask, &oldmask);//将newmask中的SIGQUIT阻塞掉,并保存当前信号屏蔽字,原来值读到oldmask.

 

        sleep (5);//休眠5秒钟

 

        sigpending(&pendmask);//检查信号是否SIGQUIT被阻塞还没有被处理

 

        if (sigismember(&pendmask, SIGQUIT))//SIGQUIT被阻塞还没有被处理

        

                printf("\\nSIGQUIT pending\\n");

        

 

        sigprocmask(SIG_SETMASK, &oldmask, NULL);//恢复被屏蔽的信号SIGQUIT

 

        printf("SIGQUIT unblocked\\n");

 

        sleep(5);//再次休眠5秒钟

 

        return (0);

 

 

测试信号集

实验结果:

 

实验代码:

#include<signal.h>

#include<stdio.h>

#include<stdlib.h>

 

int output(sigset_t set);

 

int main()

        sigset_t set;

        printf("after empty the set:\\n");

        sigemptyset(&set);

        output(set);

 

        printf("after add signo=7:\\n");

        sigaddset(&set,7);

        output(set);

        printf("after add signo=13:\\n");

        sigaddset(&set,13);

        output(set);

 

        return 0;

 

int output(sigset_t set)

        int i=0;

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

        

                printf("0x%8x\\n", set.__val[i]);

                if((i+1)%8==0)

                        printf("\\n");

        

         

 

 

 

 

 

以上是关于linux进程间通信异步信号处理机制的主要内容,如果未能解决你的问题,请参考以下文章

异步机制

进程间通信--信号(进程间通信唯一的异步方式)

《Linux应用进程间通信 — 信号》

Linux 进程间通信 --信号

Linux系统编程——进程间通信:信号中断处理

Linux-信号的本质