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 #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
22222222222222222222222222
3333333333333333333333333
上一篇: 以太网数据帧相关
下一篇: iOS开发火星坐标系与地球坐标系解析