欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-31 10:29:01
一、什么是信号? 《1》信号是用来向进程通知事件 《2》每个信号已SIG开头,信号名定义在#include 二、进程收到信号,可以做出三种措施 《1》忽略信号 《2》捕获...

一、什么是信号?

《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
#include
#include
#include
#include
#include
#include
#include
#include

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
#include
#include
#include
#include
#include
#include
#include
#include
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

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

22222222222222222222222222

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

3333333333333333333333333

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