• Linux网络编程学习(五) ----- 信号(第四章)


    1、基本概念

    进程阻塞:

    进程执行条件得不到满足,就自动放弃CPU资源而进入休眠状态,以等待条件满足,当条件满足时,系统就将控制权还给该进程进行未完成的操作

    共享资源:

    进程间协调使用的系统资源

    锁定:

    当某个进程使用共享资源时,可能需要防止别的进程对该资源的使用。Linux提供一些方法保证共享资源被某个进程使用时,其他进程不能使用,就称为共享资源的锁定

    2、信号

    信号的作用是通知一个或多个进程异步事件的发生,也可以用来处理某种严重的错误,可以从内核发往进程,也可以从一个进程发往另一个进程,

    例如:用户在后台启动了一个程序,现在想要终止此进程的执行,就可以使用Kill命令将SIGTERM信号发送给这个进程,SIGTERM将终止该进程的执行

    例如:执行exit()时,就向子进程的父进程发送SIGCHLD信号(子进程结束信号),若此时父进程在执行wait(),则父进程会被唤醒,若不是在执行wait(),则此父进程不会捕捉到SIGCHLD信号,该信号就不起作用,子进程进入过渡状态(如果父进程忽略SIGCHLD,子进程就会结束而不会进入过渡状态)

    在大多数情况下,当进程收到一个信号时,会被正常终止,相当于进程执行了一个临时加入的exit()调用。

    信号SIGQUIT、SIGILL、SIGTRAP、SIGFPE会导致一个非正常终止,它们将发生核心转贮,也就是把进程的内存映像写入进程当前目录的core文件中,core文件以二进制形式记录了终止时程序中全部变量值、硬件寄存器值和内核中的控制信息,非正常终止进程的退出状态除了其低端第7位置位外,其他与通过信号正常终止时一样

    3、信号的复位

    当一个信号的信号处理函数执行时,该进程又收到了同样的信号,那么该信号将会被存储而不会中断信号处理函数,直到信号处理函数执行完后重新调用相应处理函数,但是如果接收到了其他类型的信号,那么该信号处理函数将会被中断

    例如:

    #include <signal.h>
    int interrupt()
    {
    	printf(“Interrupt called
    ”);
    	sleep(3);
    	printf(“Interrupt Func Ended.
    ”);
    }
    main()
    {
    	signal(SIGINT,interrupt);
    	printf(“Interrupt set for SIGINT
    ”);
    	sleep(10);
    	printf(“Program NORMAL ended.
    ”);
    	return;
    }
    

      执行结果就是

    Interrupt set for SIGINT
    <ctrl+c>
    Interrupt called
    <ctrl+c>
    Func Ended
    Interrupt called
    Func Ended
    Program NORMAL ended.
    

      而代码:

    #include <signal.h>
    int interrupt()
    {
    	printf(“Interrupt called
    ”);
    	sleep(3);
    	printf(“Interrupt Func Ended.
    ”);
    }
    int catchquit()
    {
    	printf(“Quit called
    ”);
    	sleep(3);
    	printf(“Quit ended.
    ”);
    }
    main()
    {
    	signal(SIGINT,interrupt);
    	signal(SIGQUIT,catchquit);
    	printf(“Interrupt set for SIGINT
    ”);
    	sleep(10);
    	printf(“Program NORMAL ended.
    ”);
    	return;
    }
    

      执行的结果是

    Interrupt set for SIGINT
    <ctrl+c>
    Interrupt called
    <ctrl+>
    Quit called
    Quit ended.
    Interrupt Func Ended.
    Program NORMAL ended.
    

      还有就是同一种信号不能累积,如:

    Interrupt set for SIGINT
    <ctrl+c>
    Interrupt called
    <ctrl+c><ctrl+c><ctrl+c>
    Func Ended
    Interrupt called
    Func Ended
    Program NORMAL ended.
    

      如果两个信号同时产生,系统不保证进程接收的顺序,因此,信号处理的顺序就不可控

    4、进程间发送信号

    一个进程可以通过signal()调用来处理其他进程发送来的信号,同时也可以通过kill(pid_t pid,int sig)来向其他进程发送信号。pid指定了信号发送的对象进程。可以是进程标识符,也可以是以下的值

    1)pid = 0,  则信号被发送到当前进程所在的进程组的所有进程

    2)pid = -1, 则信号按进程标识符从高到低的顺序发送给全部的进程

    3)pid < -1,则信号被发送给标识符为pid 绝对值的进程组里的所有进程

    信号发送的限制:普通用户进程只能向具有与其相同的用户标识符的进程发送信号,也就是说一个用户的进程不能向另一个用户的进程发送信号,只有root用户的进程才能给任何进程发送信号。

    由于Kill需要知道目标进程标识符,所以一般在父子进程之间进行信号发送

    举个例子:两个进程,通过发送SIGUSER1实现同步,两个进程都处于死循环中,接收对方信号前,处于暂停等待中,也就是pause(),使得程序暂停一直到信号达到,然后进程输出信息,并用kill发送一个信号给对方,若用户按了中断键,两个进程终止

    #include <signal.h>
    int ntimes = 0;
    main()
    {
    	int pid,ppid;
    	int p_action(), c_action();
    	/* 设定父进程的SIGUSR1 */
    	signal(SIGUSR1,p_action);
    	switch(pid = fork()) 
    	{
    		case -1: /*fork 失败*/
    			perror("synchro");
    			exit(1);
    		case 0: /*子进程模块*/
    		/* 设定子进程的SIGUSR1 */
    			signal(SIGUSR1,c_action);
    			/* 获得父进程的标识符 */
    			ppid = getppid();
    			for(;;) 
    			{
    				sleep(1);
    				kill(ppid,SIGUSR1);
    				pause();
    			}
    			/*死循环*/
    			break;
    		default: /*父进程模块*/
    			for (;;) 
    			{
    				pause();
    				sleep(1);
    				kill(pid,SIGUSR1);
    			}
    			/*死循环*/
    	}
    }
    int p_action()
    {
    	printf("Patent caught signal #%d
    ",++ntimes);
    }
    int c_action()
    {
    	printf("Child caught signal #%d
    ",++ntimes);
    }
    

      运行结果就是

    Patent caught signal #1
    Child caught signal #1
    Patent caught signal #2
    Child caught signal #2
    Patent caught signal #3
    Child caught signal #3
    Patent caught signal #4
    Child caught signal #4
    <ctrl+c>
    

      

  • 相关阅读:
    软件架构师是如何工作
    安装flume由于HBASE出现的错误
    学习记录(Python集合)
    bzoj4199: [Noi2015]品酒大会
    清橙A1484
    codeforces 232D Fence
    bzoj2337: [HNOI2011]XOR和路径
    bzoj3143: [Hnoi2013]游走
    codeforces 235 B. Let's Play Osu!
    bestcoder单调区间
  • 原文地址:https://www.cnblogs.com/xqn2017/p/8891121.html
Copyright © 2020-2023  润新知