守护进程、系统日志、软中断信号

守护进程

1. daemon进程

  • Unix/Linux中的守护进程(Daemon)类似于Windows中的后台服务进程,一直在后台长时间运行的进程。
  • 守护进程通常在系统启动后就运行,没有控制终端,也无法和前台的用户交互,在系统关闭时才结束。
  • Daemon程序一般都作为服务程序使用,等待客户端程序与它通信。我们也把运行的Daemon程序称作守护进程
  • daemon进程一旦启动就能在后台一直运行,不会随着terminal的退出而结束。
  • 守护进程需要使用ps aux命令查出进程ID然后再使用kill命令停止。

daemon()库函数

函数原型:

#include <unistd.h>
int daemon(int nochdir, int noclose);

函数功能:

  • 创建daemon进程。

参数说明:

  • nochdir:指定是否要切换当前工作路径到/根目录,
  • noclose:指定是否要关闭标准输入、标准输出和标准出错(即重定向到/dev/null)。
  • 在创建守护进程的时候,往往需要将进程的工作目录修改为"/"根目录,并将标准输入、标准输出和标准出错关闭。所以这两个参数我们一般都是传0。

系统日志

  • syslog是一种工业标准的协议,可用来记录设备的日志。
  • 在UNIX系统,路由器、交换机等网络设备中,系统日志(System Log)记录系统中任何时间发生的大小事件。管理者可以通过查看系统记录,随时掌握系统状况。
  • UNIX的系统日志是通过syslogd这个进程记录系统有关事件记录,也可以记录应用程序运作事件。
  • 通过适当的配置,可以实现运行syslog协议的机器间通信,通过分析这些网络行为日志,追踪掌握与设备和网络有关的状况。

Linux系统自带的日志系统 syslog 函数

openlog()

函数原型:

#include <syslog.h>
void openlog(const char *ident, int option, int facility);

函数功能:

  • 打开日志设备,以供读取和写入,与文件系统调用的open类似;调用openlog是可选择的。如果不调用openlog,则在第一次调用syslog时,自动调用openlog。

参数说明:

  • ident:是一个标记,ident 所表示的字符串将固定的加在每行日志的前面来标识这个日志,通常就写成当前程序的名称以作标记。
  • option: 指定openlog函数和接下来调用的syslog函数的控制标志。可以取以下值:
option说明
LOG_CONS如果将信息发送给 syslogd 守护进程时发生错误,直接将相关信息输出到终端
LOG_NDELAY立即打开与系统日志的连接(通常情况下,只有在产生第一条日志信息的情况下才会打开与日志系统的连接)
LOG_ODELAY类似于 LOG_NDELAY 参数,与系统日志的连接只有在 syslog 函数调用时才会创建
LOG_PERROR在将信息写入日志的同时,将信息发送到标准错误输出
LOG_PID每条日志信息中都包含进程号
  • facility:指定记录消息程序的类型,与 syslogd 守护进程的配置文件 syslog.conf 中的 facility 对应。可取如下值:
facility说明
LOG_AUTH认证系统(login、su、getty等)
LOG_AUTHPRIV同 LOG_AUTH 但只登陆到所选择的单个用户可读的文件中。
LOG_CRONcron 守护进程
LOG_DAEMON其他系统守护进程,如 routed
LOG_FTP文件传输协议:ftpd、tftpd
LOG_KERN内核产生的消息
LOG_LPR系统打印机缓冲池:lpr、lpd
LOG_MAIL电子邮件系统
LOG_NEWS网络新闻系统
LOG_SYSLOG由 syslogd(8)产生的内部消息
LOG_USER随机用户进程产生的消息
LOG_UUCP UUCP子系统
LOG_LOCAL0 ~ LOG_LOCAL7本地使用保留

syslog()

函数原型:

void syslog(int priority, const char *format, …);

函数说明:

  • 写入日志,与文件系统调用 printf使用方法类似,但在前面指定日志级别。

参数说明:

  • priority:表示消息的级别,与 syslogd 守护进程的配置文件syslog.conf 中的 level 对应。可取如下值:
priority说明
LOG_EMERG紧急情况
LOG_ALERT应该被立即改正的问题,如系统数据库破坏
LOG_CRIT重要情况,如硬盘错误
LOG_ERR错误
LOG_WARNING警告信息
LOG_NOTICE不是错误情况,但是可能需要处理
LOG_INFO情报错误
LOG_DEBUG包含情报的信息,通常指在调试一个程序时使用

closelog()

函数原型:

void closelog(void);

函数说明:

  • 关闭日志设备,与文件系统调用的close类似;调用closelog也是可选择的,它只是关闭被用于与syslog守护进程通信的描述符。

软中断信号

  • 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。
  • 异步事件:不知道事件什么时候发生。
  • 信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。
  • 进程之间可以互相通过系统调用kill()发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。
  • 信号机制除了基本通知功能外,还可以传递附加信息。 收到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:
  1. 第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理。
  2. 第二种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。
  3. 第三种方法是,对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为
  • kill -l 命令:查看当前系统支持的信号,不同的系统支持的信号是不一样的。
  • 信号值位于SIGRTMINSIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。
信号编号信号名信号说明默认动作
2SIGINTCtrl+C按键终止程序运行的信号程序终止
4SIGILL非法的指令程序终止
7SIGBUS运行非本CPU相关编译器编译的程序程序终止
9SIGKILL强制杀死程序信号,任何程序都不可以捕捉该信号程序终止,不可被捕捉
10SIGUSR1用户自定义信号1程序终止
11SIGSEGV段错误系统给程序发送的信号程序终止
12SIGUSR2用户自定义信号2程序终止
13SIGPIPE管道破裂信号程序终止
14SIGALRMalarm()系统调用发送的信号程序终止
15SIGTERMkill命令默认发送的信号,默认动作是终止信号程序终止
17SIGCHLD子进程退出信号忽略该信号

signal()库函数

  • 不安全,可能导致信号丢失。

函数原型:

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

代码演示:

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

int g_stop = 0;

void sig_handle(int signum)
{
        printf("catch signal [%d]\n",signum);
        g_stop = 1;
}

int main(void)
{
        signal(SIGINT,sig_handle);
        signal(SIGTERM,sig_handle);

        while( !g_stop )
        {
                ;
        }
        printf("power off gprs\n");
}

  • 执行代码后,用ctrl+c关闭进程,结果如下:

^Ccatch signal [2]
power off gprs

  • 执行代码后,用kill关闭进程,结果如下:

catch signal [15]
power off gprs

sigaction()库函数

  • 安全

代码演示:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <execinfo.h>

int g_sigstop = 0;

void signal_stop(int signum)
{
        if( SIGTERM == signum )
        {
                printf("SIGTERM signal detected\n");
        }
        else if( SIGALRM == signum )
        {
                printf("SIGALRM signal detected\n");
                g_sigstop = 1;
        }
}

void signal_user(int signum)
{
        if(SIGUSR1 == signum)
        {
                printf("SIGUSR1 signal detected\n");
        }
        else if(SIGUSR2 == signum)
        {
                printf("SIGUSR2 signal detected\n");
        }

        g_sigstop = 1;
}
void signal_code(int signum)
{
        if(SIGBUS == signum)
        {
                printf("SIGBUS signal detected\n");
        }
        else if(SIGILL == signum)
        {
                printf("SIGILL signal detected\n");
        }
        else if(SIGSEGV == signum)
        {
                printf("SIGSEGV signal detected\n");
        }

        exit(-1);
}

int main(int argc, char **argv)
{
        char *ptr=NULL;
        struct sigaction sigact, sigign;

        signal(SIGTERM, signal_stop);
        signal(SIGALRM, signal_stop);

        signal(SIGBUS, signal_code);
        signal(SIGILL, signal_code);
        signal(SIGSEGV, signal_code);

        sigemptyset(&sigact.sa_mask);
        sigact.sa_flags = 0;
        sigact.sa_handler = signal_user;

        sigaction(SIGUSR1, &sigact, 0); /* catch SIGUSR1 */
        sigaction(SIGUSR2, &sigact, 0); /* catch SIGUSR1 */

        sigemptyset(&sigign.sa_mask);
        sigign.sa_flags = 0;
        sigign.sa_handler = SIG_IGN;

        sigaction(SIGINT, &sigign, 0); /* ignore SIGINT signal by CTRL+C */

        printf("Program start running for 20 seconds...\n");
        alarm(20);

        while( !g_sigstop )
        {
                 ;
        }

        printf("Program start stop running...\n");

        printf("Invalid pointer operator will raise SIGSEGV signal\n");
        *ptr = 'h';

        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值