一、什么是信号?
《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