linux中的信号及进程守护应用实例

一、什么是信号?

《1》信号是用来向进程通知事件
《2》每个信号已SIG开头,信号名定义在#include

二、进程收到信号,可以做出三种措施

《1》忽略信号
《2》捕获,需要执行一段信号处理的特殊代码
《3》允许执行信号的默认操作

三、相关函数

《1》pause()函数,一直暂停等待
挂起调用它的进程,直到任何消息到达
发送信号和捕获信号是相辅相成的,每个信号除了决定响应SIGSTOP和SIGKILL外的其他进程,这两个消息不可以被忽略
《2》回调函数
含义:函数指针作为参数传递给另外一个函数,当这个指针被用来调用其所指函数时,称为回调函数
《3》捕捉信号所用的函数
(1)signal函数

void* signal(int signo, void(*func)(int));
int signo//捕捉什么信号
void(*func)(int)//捕捉信号的回调函数

(2)sigaction函数

int sigaction(int signo,const struct sigaction* act,struct sigaction* oact)
//int signo:要捕捉的信号
//const struct sigaction* act:信号现处的状态
//struct sigaction* oact返回之前的状态

鉴于,signal函数有些古老,使用的时候,会出现一些问题,建议使用sigaction,但是,该函数参数有些复杂,所以可以封装一个函数, 每次调用即可,下面为封装方法:

int signal1(int signo,void(*func)(int))
{
    struct sigaction act,oact;
    act.sa_hardler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    return sigaction(signo,&act,&oact);
}

每次需要捕捉信号的时候,只用在主调函数中调用signal1就可以了signal1(SIGINT,catch_signal);
《4》kill相关函数
《1》使用kill命令
《2》使用kill函数

int kill(pid_t pid,int sig)
//pid_t pid:指定要杀死的进程,将信号发送给进程
//int sig:发送的进程

《5》raise()函数

int raise(int signo)
//等价于kill(getpid(),signo)

《6》alarm()函数
alarm函数设置一个计时器,当计时器到了就发送一个SIGALRM信号

unsigned int alarm(unsigned int seconds)

《7》abort()函数
当执行abort函数时,会发送一个SIGABRT信号,导致信号进程异常终止

void abort(void)

四、守护进程

《1》创建守护进程步骤总结
(1)父进程中执行fork后,执行exit()退出;
(2)在子进程中调用setsid()
(3)让根目录”/”成为子进程的工作目录
(4)将子进程的umusk变为0
(5)关闭任何不需要的文件描述符
《2》pid_t setsid()
用来创建一个新会话和一个新进程组,然后守护进程成为新会话和新进程组的领导;

该函数一旦调用,就不再拥有任何控制终端,可以通过svslog提供服务,记录守护进程的各种输出的信息;

《3》chdir

int chdir(const char* pathname)
//改变当前目录
//例如,在主函数中调用 : chdir("/");

五、应用实例

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>

void readfifo()//读取fifo管道文件内容
{
    int len = 0;
    char buf[1024];
    memset(buf, 0 ,sizeof(buf));
    int fd = open("/home/dw/dwcode/fifo1",O_RDONLY);
    if(fd == -1)
    {   
        printf("open fifo error%s\n",strerror(errno));
        return ;
    }
    while((len = read(fd,buf,sizeof(buf)))> 0)//循环读取管道内容,直到管道文件被关闭,循环结束
    {
        printf("%s\n",buf);
        memset(buf ,0, sizeof(buf));
    }   
    close(fd);
    return;
}
void setdaemon()//把程序设置为deamo状态
{
    pid_t pid = fork();
    if(pid  == -1)
    {
        printf("fork error!\n");
        exit(0);
    }
    if(pid > 0)
       {
        exit(0);
    }
    if(pid == 0)
        {
        setsid();
        chdir("/");
        /*umask(0);
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
                 */ 
}
}

int main(int arg,char*args[])
{
    setdaemon();    
    readfifo();
    return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
void writefifo()//写数据到管道
{
    int len = 0;
    char buf[1024];
    memset(buf , 0 ,sizeof(buf));
    int fd = open("/home/dw/dwcode/fifo1",O_WRONLY);
    if(fd == -1)
    {
        printf("write fifo1 error%s\n",strerror(errno));
        return ;

    }
while(1)
{
    memset(buf,0,sizeof(buf));
    scanf("%s",buf);
    write(fd, buf, sizeof(buf));

}   close(fd);
    return ;

}

int main()
{
    writefifo();
    return 0;
}
.SUFFIXES:.c .o//makefile的书写
CC=gcc
SRCS1=readfifo.c
SRCS2=writefifo.c

OBJS1=$(SRCS1:.c=.o)
OBJS2=$(SRCS2:.c=.o)

EXEC1=readfifo
EXEC2=writefifo

all:$(OBJS1) $(OBJS2)
    $(CC) -o $(EXEC1) $(OBJS1)
    $(CC) -o $(EXEC2) $(OBJS2)
    @echo '^-^ ^-^ ^-^ ^-^ok ^-^ ^-^ ^-^ ^-^'
.c .o:
    $(CC) -Wall -g -o $@  -c $<
clean:
    rm -f $(OBJS)
    rm -f core*

11111111111111111111111111

22222222222222222222222222

3333333333333333333333333

猜你喜欢

转载自blog.csdn.net/dai_wen/article/details/79834764