Linux环境编程

Linux信号处理

一、基本概念

    1、中断

        当程序接受到消息后中止当前正在执行的程序,转而执行其他任务,等其他任务执行完后再返回,这种执行模式叫做中断

        分为硬件中断和软件中断

    2、信号

        是一种软件中断,由操作系统发出,程序接受后执行相应的操作

    3、常见的信号

        命令 kill -l 查看所有信号

        SIGINT(2)   Ctrl+c         终止

        SIGQUIT(3)  Ctrl+\         终止+core

        SIGFPE(8)   除零            终止+core

        SIGKILL(9)  终止信号        终止   不能捕获、忽略

        SIGSEGV(11) 非法访问内存    终止+core  

    4、不可靠信号和可靠信号

        建立在早期的信号处理机制上(1~31)的信号不可靠信号

            不支持排队、可能会丢失,如果同一个信号连续产生多次,进程可能只响应了一次

        建立在新的信号处理机制上(34~64)的信号是可靠信号

            支持排队、信号不会丢失

    5、信号的来源

        硬件来源:除零、非法访问内存、未定义的指令、总线错误

        软件异常:通过一些命令、函数产生的信号

    6、信号的处理方式

        1、忽略

        2、终止进程

        3、终止进程并产生core文件(记录内存映像)

        4、停止

        5、继续

        6、捕获并处理(重点) (在信号发生前,先向内核注册一个函数,当信号来临时系统会自动执行该函数)

二、信号捕获

    typedef void (*sighandler_t)(int);

    功能:说明信号处理函数的格式

    sighandler_t signal(int signum, sighandler_t handler);

    功能:向内核注册一个信号处理函数

    signum: 信号编号

    handler: 函数指针

        也可以使用以下参数

        SIG_IGN 忽略

        SIG_DFL 按默认方式处理

    返回值:

        之前的信号处理方式

    注意:

        1、SIGKILL(9)和SIGSTOP(19)信号不能被捕获和忽略处理

        2、当信号处理完后可能会返回产生信号的代码继续运行,如果我们捕获并处理段错误、算术异常等信号可能会产生死循环

            正确的处理段错误、算术异常信号应该是备份数据并直接结束程序

        3、有些系统通过signal注册的信号处理函数只能执行一次,如果想要持续有效,可以在信号处理函数中再重新注册一次

        4、子进程会继承父进程的信号处理方式,但是通过exec系列函数创建的子进程,会恢复默认的信号处理方式

    信号的发送方式

    1、键盘

        Ctrl+c

        Ctrl+\

        Ctrl+z  暂停\挂起  fg继续

    2、错误

        除零

        非法访问内存

        总线错误

    3、命令

        kill -信号编号 进程号

        功能:向指定的进程发送信号

        killall -信号编号 进程名

            可以给同名进程发送同一个信号

    4、函数

        int kill(pid_t pid, int sig);

        功能:向指定进程发送指定信号

        pid: 进程号

        sig: 信号编号

        int raise(int sig)

        功能: 向进程自己发送信号sig

        void abort(void)

        功能: 向进程自己发送信号SIGABRT

        unsigned int alarm(unsigned int seconds);

        功能: 让内核在seconds秒后进入

三、进程休眠信号

    int pause(void)

    功能:让调用者进入休眠状态,直到进程遇到信号才会唤醒

    返回值:要么不返回在休眠,要么唤醒后返回-1

    相当于没有时间限制的sleep

    unsigned int sleep(unsigned int seconds)

    功能:让调用者进入休眠指定的秒数,当遇到信号时会提前唤醒返回

    返回值:剩余的休眠时间

四、信号集和信号阻塞

    信号集: 是一种数据类型,定义的变量可以存储多个信号

    sigset_t 128位的二进制数,每一位都固定代表了一种信号

    相关函数:

        int sigemptyset(sigset_t *set);

        功能:清空信号集

        int sigfillset(sigset_t *set);

        功能:填满信号集

        int sigaddset(sigset_t *set,int signum);

        功能: 向信号集set中添加信号signum

        int sigdelset(sigset_t *set,int signum);

        功能: 向信号集set中删除信号signum

        int sigisember(const sigset_t *set,int signum);

        功能: 测试信号计中是否存在signum信号

            返回值:

                0   不存在

                1   存在

                -1  signum信号非法

    信号阻塞:

        当程序执行到一些特殊的操作时,不适合处理信号,此时可以让内核屏蔽信号,等操作执行完成后再解除屏蔽重新发送

        当信号产生时,内核会在其维护的信号表中为对应的进程设置与该信号对应的标记,这个过程叫做递送

        信号产生到完成递送有个时间间隔,处于这个间隔的信号状态称为未决

        信号屏蔽\阻塞就是让被频闭的信号先处于未决状态、暂停递送,当屏蔽解除时再继续递送

    int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

    功能:设置要屏蔽的信号、这些信号是存储在信号集里面

    how: 信号屏蔽集

        SIG_BLOCK     把set中的信号添加到要屏蔽的信号集里

        SIG_UNBLOCK   从信号屏蔽集中删除set中的信号 解除

        SIG_SETMASK   把set替换之前的信号屏蔽集

    set: 准备好的信号集

    oldset: 获取旧的信号屏蔽器

五、附带信息的信号处理

    int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

    功能:向内核注册一个信号处理函数

    signum: 要注册的信号编号

    act: 设置要处理的动作

    olact: 获取原来的处理动作

    struct sigaction {

        void     (*sa_handler)(int); // 不附带其他信息的信号处理函数

        void     (*sa_sigaction)(int, siginfo_t *, void *); //  附带其他信息的信号处理函数

        sigset_t   sa_mask; //  信号屏蔽集

        int        sa_flags; //  信号处理动作标志

            SA_NODEFER    在信号处理过程中不要屏蔽当前信号

            SA_SIGINFO    使用sa_sigaction  函数指针

        void     (*sa_restorer)(void); //  保留函数

    };

    siginfo_t {

        int      si_signo;     /* Signal number */

        int      si_errno;     /* An errno value */

        int      si_code;      /* Signal code */

        int      si_trapno;    /* Trap number that caused

                                         hardware-generated signal

                                         (unused on most architectures) */

        pid_t    si_pid;       /* Sending process ID */

        uid_t    si_uid;       /* Real user ID of sending process */

        int      si_status;    /* Exit value or signal */

        clock_t  si_utime;     /* User time consumed */

        clock_t  si_stime;     /* System time consumed */

        sigval_t si_value;     /* Signal value */

        int      si_int;       /* POSIX.1b signal */

        void    *si_ptr;       /* POSIX.1b signal */

        int      si_overrun;   /* Timer overrun count;

                                         POSIX.1b timers */

        int      si_timerid;   /* Timer ID; POSIX.1b timers */

        void    *si_addr;      /* Memory location which caused fault */

        long     si_band;      /* Band event (was int in

                                         glibc 2.3.2 and earlier) */

        int      si_fd;        /* File descriptor */

        short    si_addr_lsb;  /* Least significant bit of address

                                         (since Linux 2.6.32) */

        void    *si_call_addr; /* Address of system call instruction

                                         (since Linux 3.5) */

        int      si_syscall;   /* Number of attempted system call

                                         (since Linux 3.5) */

        unsigned int si_arch;  /* Architecture of attempted system call

                                         (since Linux 3.5) */

    }

    int sigqueue(pid_t pid,int sig,const union sigval value);

    功能:向指定进程发送信号并附加信息一起发送

    union sigval {

        int sival_int; //  整数

        void *sival_ptr; //  指针

    }

六、定时器

    #include <sys/time.h>

    int gettimer(int which,struct itimerval *curr_value);

    功能:获取当前的定时方案

    which: 选择使用的计时器

        ITIMER_REAL     真实计时器 程序总的计时时间

        ITIMER_VIRTUAL  虚拟计时器 用户态的计时

        ITIMER_PROF     实际计时器 用户态+内核态计时

        真实计时器 = 实际计时器 + 休眠时间 + 切换时间

    int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);

    功能:设置定时器计时方案

        which: 选择使用的计时器

        ITIMER_REAL     真实计时器 程序总的计时时间SIGALRM(14)

        ITIMER_VIRTUAL  虚拟计时器 用户态的计时SIGVTALRM(26)

        ITIMER_PROF     实际计时器 用户态+内核态计时

        SIGPROF(27)


 

        struct itimerval {

            struct timeval it_interval;   //  每次时钟信号产生的间隔时间

            struct timeval it_value;      //  第一次产生时钟信号的时间

        };

        struct timeval {

            time_t tv_sec   //  设置秒

            suseconds_t tv_usec;  //  设置微妙50000

        };

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux环境编程图文指南是一本详细介绍在Linux系统下进行编程的指南。它包含了图文并茂的内容,帮助读者理解和掌握Linux环境下的编程技巧和方法。 首先,该指南会介绍Linux系统的基本组成和架构,帮助读者了解Linux的工作原理和基本操作。它还会详细介绍如何在Linux系统上安装和配置开发环境,包括编译器、编辑器和调试工具的选择和设置。 其次,该指南会深入讲解Linux环境下的编程语言和工具。它会介绍C语言、Python和Shell脚本等常用的编程语言,并提供详细的语法和示例代码。此外,它还会介绍一些常用的开发工具和库,如GCC、Make、GDB和GTK+等,帮助读者更高效地进行编程和调试。 除了基本的编程技巧,该指南还会介绍Linux系统的特性和机制。它会介绍Linux的进程管理、文件系统和网络编程等相关内容,帮助读者深入理解Linux系统的工作原理,并能够针对特定需求进行系统级的编程和定制。 最后,该指南还会提供一些实际案例和示例项目,帮助读者将所学知识应用到实际的项目开发中。这些案例涵盖了网络应用、系统管理和嵌入式开发等不同领域,读者可以根据自己的兴趣和需求选择学习和实践。 总之,Linux环境编程图文指南为读者提供了一个全面而系统的学习资源,帮助他们在Linux系统下进行编程并取得成功。无论是初学者还是有一定经验的开发者,该指南都可以成为他们的参考和指导。 ### 回答2: Linux环境编程图文指南是一本介绍在Linux操作系统下进行编程的指南。本书旨在帮助读者从零基础开始学习Linux环境下的编程知识,并提供实用的例子和案例,帮助读者更好地理解和应用所学的知识。 首先,本书会介绍Linux操作系统的基础知识,包括Linux的发行版、命令行界面、文件系统结构等。读者可以逐步学习如何在Linux环境下进行基本的文件操作、目录管理和进程管理等。 接着,本书会详细介绍Linux下的编程环境和工具,如GCC编译器、GNU调试器、Makefile等。读者可以学习如何配置和使用这些工具来进行程序的开发、编译和调试。 同时,本书还会介绍各种编程语言在Linux环境下的应用,如C、C++、Python、Shell等。读者可以学习这些语言的基本语法和特性,并了解如何在Linux环境下使用这些语言编写各种类型的程序。 在实际编程方面,本书将提供大量的实例和案例,涵盖了各种不同的应用场景,如网络编程、多线程编程、系统编程等。读者可以通过这些实例和案例的学习和实践,掌握不同类型的编程技巧和方法。 最后,本书还会介绍一些常用的软件开发工具和技术,如版本控制系统(如Git)、协作开发工具(如GitHub)、自动化测试工具等。读者可以了解和应用这些工具和技术,提高编程效率和代码质量。 总而言之,Linux环境编程图文指南是一本全面介绍在Linux操作系统下进行编程的指南。通过阅读本书,读者可以系统地学习和掌握在Linux环境下的编程知识和技能,为自己的编程之路打下坚实的基础。 ### 回答3: Linux环境编程是一种在Linux操作系统下进行软件开发和编程的技术。它提供了一个强大的开发环境,可以满足各种不同的编程需求。 首先,我们需要熟悉Linux操作系统的基本命令和操作。这些包括文件和目录的创建、删除、复制、移动等操作,以及文件权限、用户管理等基本概念。掌握这些基础知识将有助于我们更好地理解和使用Linux环境。 其次,我们需要选择一个适合的集成开发环境(IDE)或文本编辑器。常用的IDE包括Eclipse、NetBeans和Code::Blocks,它们提供了强大的代码编辑、调试和项目管理功能,可以提高开发效率。另外,对于轻量级编程任务,使用文本编辑器(如Vim或Emacs)也是不错的选择。 接下来,我们需要具备编程语言的基本知识。在Linux环境下,常用的编程语言包括C、C++、Java、Python等。我们需要学习这些语言的语法、数据结构、算法等基础知识,以便能够编写出高效、可靠的程序。 在编写程序时,我们可以利用Linux环境提供的各种工具和库。例如,我们可以使用gcc编译器来编译C和C++程序,使用Java虚拟机(JVM)来运行Java程序。此外,Linux环境还提供了丰富的库,如GNU C库(glibc)、GTK+和Qt等,它们能够帮助我们进行图形界面开发、网络编程等任务。 最后,我们还需要学会使用调试工具来调试程序。在Linux环境下,我们可以使用gdb来进行源代码级别的调试,它提供了诸如设置断点、查看变量、追踪函数调用等功能,帮助我们定位和修复程序中的错误。 总之,掌握Linux环境编程需要建立在对Linux操作系统的基本了解和掌握的基础上,并结合相应的编程语言和工具。只有理论和实践相结合,才能真正掌握这一技能,并在实际项目中得到应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值