Linux中fork的进一步加深及信号基础

1.通过题目理解fork

    1.打印结果?产生了几个进程?

#include  <stdio.h>
#include  <unistd.h>
#include  <stdlib.h>

int main()
{
    int i=0;
    for(;i<2;i++)
    {
        fork();
        printf("A\n");
    }
    exit(0);
}

所以打印6个A;

2.如果改为printf("A"),打印结果?


3.打印结果?

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
     printf("A");
     fork();
     exit(0);
}

打印两个A,因为缓冲区里面有一个;

4.如果改为printf("A\n"),打印结果?

只打印一个A,因为已经打印了,缓冲区没有了;

5.打印结果?

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    fork()||fork();
    printf("A\n");
    exit(0);
}

所以打印3个A;

6.第7行改为fork()&&fork之后打印结果是多少?

同理,注意短路现象即可;

所以打印3个A;

7.把第6题,第7题目的\n去掉影响结果不?

不影响;

因为是先fork,然后打印的时候放入缓冲区了,但是接着退出了,刷新缓冲区了,所以不影响;

8.打印结果?

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    printf("A");
    write(1,"B",1);
    fork();
    exit(0);
}

先放入缓冲区,然后打印B,然后复制了一个子进程(子进程缓冲区也有一个A),然后父进程退出刷新缓冲区打印A,子进程也退出刷新缓冲区打印A;

所以结果是BAA;

9.第1题,第2题先打印再fork结果是什么?

#include  <stdio.h>
#include  <unistd.h>
#include  <stdlib.h>

int main()
{
    int i=0;
    for(;i<2;i++)
    {
        printf("A\n");
        fork();       
    }
    exit(0);
}

打印3个A;

i=0,打印A,然后fork;

之后i=1,打印A;                i=1,打印A

第二题先打印后fork:

#include  <stdio.h>
#include  <unistd.h>
#include  <stdlib.h>

int main()
{
    int i=0;
    for(;i<2;i++)
    {
        printf("A");
        fork();       
    }
    exit(0);
}

2.信号

(1)信号的基本介绍

信号是系统响应某个条件而产生的事件,进程接收到信号会执行相应的操作;
与信号有关的系统调用在<signal.h>头文件中.

1)信号的存储位置

vim    /usr/include/x86_64-linux-gnu/bits/signum.h   旧版

新版(23版)

vim    /usr/include/x86_64-linux-gnu/bits/signum-arch.h

vim    /usr/include/x86_64-linux-gnu/bits/signum-generic.h

2)常见信号对应的功能

SIGABORT       *进程异常终止

SIGALRM         超时警告

SIGFPE            *浮点运算异常

SIGHUP           连接挂断

SIGILL               *非法指令

SIGINT              终端中断

SIGKILL             终止进程(此信号不能被捕获或忽略)

SIGPIPE             向无读进程的管道写数据

SIGQUIT             终端退出

SIGSEGV             *无效内存段访问

SIGTERM               终止

SIGUSR1              用户定义信号1

SIGUSR2              用户定义信号2

...

3)信号的值

       信号名称 信号代号   

#define SIGHUP 1
#define SIGINT 2 //键盘按下 Ctrl+c 时,会产生终端中断信号
#define SIGQUIT 3//键盘按下 Ctrl+\ 时,会产生终端退出信号
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9 //该信号的响应方式不允许改变
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13 //读端关闭的描述符,写端写入时产生,该信号会终止程序(向无读进程的管道写数据)
#define SIGALRM 14
#define SIGTERM 15 //系统 kill 命令默认发送的信号
#define SIGSTKFLT 16
#define SIGCHLD 17 //子进程结束后,会默认给父进程发送该信号
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGURG 23
           ...

(2)信号的响应方式

三种响应方式:默认,忽略,自定义;

演示默认的处理方式:

也就是收到信号了,进程按照信号默认的方式去处理;

代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
int main()
{
    while(1)
    {
        printf("main run\n");
        sleep(1);
    }
    exit(0);
}

键盘按下ctrl+c时,其实就是因为该进程收到了一个信号:SIGNT----终端中断的信号.(2号信号);就是说,在键盘上按下ctrl+c时,会给当前终端前台执行的进程发送SIGINT信号;

(3)改变信号的响应方式

(1)设置信号的响应方式:通过系统调用signal();以下是对于signal中帮助手册的解释

man   signal

第二个参数为一个函数指针,它指向一个参数为int,返回值为void的一个函数;

(2)修改信号的响应方式

那如果我们改变信号的响应方式呢?

1)自定义

用signal修改SIGINT信号的响应方式示例如下

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
void sig_fun(int sig)
{
    printf("sig=%d\n",sig);
}
int main()
{
    signal(SIGINT,sig_fun);
    while(1)
    {
        printf("main run\n");
        sleep(1);
    }
    exit(0);
}

那如何结束该进程呢?

方法一:

打开另外一个终端,通过ps -ef|grep main这个命令找到该进程的pid,然后kill掉它.

方法二:

当然,我们也可以ctrl+\,这个是终端退出的信号;

2)忽略

将上面的signal函数代码修改成:
signal(SIGINT,SIG_IGN);

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
void sig_fun(int sig)
{
    printf("sig=%d\n",sig);
}
int main()
{
    signal(SIGINT,SIG_IGN);
    while(1)
    {
        printf("main run\n");
        sleep(1);
    }
    exit(0);
}

(4)信号练习题目:

收到SIGINT这个信号,第一次打印信号的代号,第二次按照默认形式把进程结束;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
void sig_fun(int sig)
{
    printf("sig=%d\n",sig);
    signal(sig,SIG_DFL);
}
int main()
{
    signal(SIGINT,sig_fun);
    while(1)
    {   
        printf("main run\n");
        sleep(1);
    }   
    exit(0);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值