linux信号通信

linux里面进程间通信的另外一种方式就是信号通信。信号通信属于软件中的。

linux有如下几个常用的信号:

SIGHUP:终端上发出的结束信号

SIGINT :来自键盘的终端信号(CTRL+C)

SIGQUIT:来自键盘的退出信号(CTRL +\)

SIGFPE:浮点异常信号

SIGKILL:该信号结束接收信号的进程

SIGALRM:进程的定时器到期,发送该信号

SIGTERM:kill发送出的信号

SIGCHLD:标识子进程停止或结束的信号

SIGSTOP:来自键盘(CTRL+Z)或调试程序的停止信号


接收方有三种动作来对待信号:

1.忽略:SIGKILL、SIGSTOP例外

2.捕捉:执行终端服务程序

3.执行系统默认动作:(1)abort(2)exit(3)ignore(4)stop(5)continue


kill() and raise() method           raise() method can send signals to the proc who invoke the raise method.

int kill(pid_t pid, int signo);

int raise(int signo);

返回值:成功,0;出错,-1.

对于kill里面的pid:pid>0:至指定pid proc;pid==0:至同进程组的其他proc;pid<0:至pid绝对值的proc。


#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
	pid_t pid;
	int ret;
	if((pid=fork())<0){
		perror("fork");
		exit(1);
	}
	if(pid == 0){
		raise(SIGSTOP);                      //向自身发送停止信号
		exit(0);
	}
	else{
		printf("pid=%d\n",pid);
		if((waitpid(pid,NULL,WNOHANG))==0){
			if((ret=kill(pid,SIGKILL))==0)
				printf("kill %d\n",pid);
			else{
				perror("kill");
			}
		}
	}
}



alarm() and pause() method.

alarm() can set a timer, when the timer is time out, then a SIGALRM signal will be sent to it.

the default action is to terminate the proc.

#include <unistd.h>

unsigned int alarm (unsigned int seconds);


pause() makes the proc which invokes it suspended, until it captures a signal.

#include <unistd.h>

int pause(void);


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

int main()
{
        int ret;
        ret=alarm(5);
        pause();
        /*printf("I have been waken up.\n",ret);*/
}


信号处理            signal()

void (*signal (int signo, void (*func));

返回:成功则为以前的信号处理配置,若出错则为SIG_ERR

func的值有三种:

(1)常数SIG_IGN

(2)常数SIG_DFL

(3)要调用的函数地址

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void my_func(int sign_no)
{
	if(sign_no==SIGINT)
		printf("I have get SIGINT\n");
	else if(sign_no==SIGQUIT)
		printf("I have get SIGQUIT\n");
}
int main()
{
	printf("Waiting for signal SIGINT or SIGQUIT \n ");
	signal(SIGINT, my_func);                                //注册SIGINT的处理函数,CTRL+C可以触发
	signal(SIGQUIT, my_func);                               //注册SIGQUIT的处理函数,CTRL+\可以触发
	pause();
	exit(0);
}


信号集函数组 signal set数据类型

#include <signal.h>

int sigemptyset ( sigset_t *set);

int sigfillset(sigset_t *set);

int sigaddset( sigset_t *set , int signo);

int sigdelset ( sigset_t *set , int signo);

返回值:成功,0;出错,-1。

int sigismember ( const sigset_t *set , int signo );

检查信号是否在信号集中。

int sigaction ( int signo, const struct sigaction *act, struct sigaction *oact);

检查或修改与指定信号相关的处理动作。

其中结构体参数 sigaction :

struct  sigaction{
     void (*sa_handler)(int signo);
     sigset_t sa_mask;
     int sa_flags;
     void (*sa_restore);
}

#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

void my_func(int signum)
{
	printf("If you want to quit,please try SIGQUIT\n");
}
int main()
{
	sigset_t set,pendset;
	struct sigaction action1,action2;
	if(sigemptyset(&set)<0)                       //empty the set
		perror("sigemptyset");                
	if(sigaddset(&set,SIGQUIT)<0)                 //add SIGQUIT signal
		perror("sigaddset");
	if(sigaddset(&set,SIGINT)<0)                  //add SIGINT signal
		perror("sigaddset");
	if(sigprocmask(SIG_BLOCK,&set,NULL)<0)        //阻塞中断
		perror("sigprocmask");
	else
	{
		printf("blocked\n");
		sleep(5);
	}
	if(sigprocmask(SIG_UNBLOCK,&set,NULL)<0)       //取消阻塞
		perror("sigprocmask");
	else
		printf("unblock\n");
	while(1){                                      //进入死循环,不断询问是否有SIGINT OR SIGQUIT信号。CTRL+C:SIGINT,CTRL+\:SIGQUIT
		if(sigismember(&set,SIGINT)){
			sigemptyset(&action1.sa_mask);
			action1.sa_handler=my_func;
			sigaction(SIGINT,&action1,NULL);
		}else if(sigismember(&set,SIGQUIT)){
			sigemptyset(&action2.sa_mask);
			action2.sa_handler = SIG_DFL;
			sigaction(SIGTERM,&action2,NULL);
		}
	}
}

守护进程

特点:生存期长;后台运行;系统引导时就装入,系统关闭时才终止

ps -e 中看到的以d结尾的进程即守护进程(daemon),终端名称为?号。

所有daemon均以超级用户的优先级运行

除了update外,所有的daemon process都是进程组的首进程

所有daemon process 的parent process 都是init process.


(1)create sub proc, terminate parent proc

(2)invoke setsid

(3)change current dir to /

(4)reset 文件权限掩码

(5)close the unneeded file descriptor


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<syslog.h>
#define MAXFILE 65535
int main()
{
	pid_t pc,sid;
	int i,fd,len;
	char *buf="This is a Dameon\n";
	len =strlen(buf);
	pc=fork();                                         //create sub process
	if(pc<0)
	{
		printf("error fork\n");
		exit(1);
	}
	else if(pc>0)                                      //terminate parent process
		exit(0);
		
	setsid();                       //1.脱离会话组;2.脱离进程组;3.脱离控制终端,变为后台进程
	chidir("/");                    //改变目录
	umask(0);                       //对所有权限开放
	for(i=0;i<MAXFILE;i++)          //关闭所有不需要的文件描述符
		close(i);
	if((fd=open("/tmp/daemon.log",O_CREATE | O_WRONLY | O_APPEND, 0600))<0)   
	{
		perror("open");
		exit(1);
	}
	while(1)
	{
		
		write(fd, buf, len+1);        //写文件
		sleep(2);                     //每两秒写一次
	}
	close(fd);
}


daemon的出错管理

通过syslog服务,将错误信息写到/var/log/message

openlog();

syslog():向日志文件里写入message

closelog();


#include <syslog.h>

void openlog( char *ident, int option, int facility );

ident: 要向每个消息加入的字符串,通常为程序名称

option: LOG_CONS, LOG_NDELAY, LOG_PERROR, LOG_PID


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<syslog.h>
         
#define MAXFILE 65535
int main()
{
	pid_t pc,sid;
	int i,fd,len;
	char *buf="This is a Dameon\n";
	len =strlen(buf);
	pc=fork();
	if(pc<0)
	{
		printf("error fork\n");
		exit(1);
	}
	else if(pc>0)
		exit(0);
	openlog("demo_update",LOG_PID, LOG_DAEMON);
	if((sid=setsid())<0)
	{
		syslog(LOG_ERR, "%s\n", "setsid");
		exit(1);
	}
	if((sid=chdir("/"))<0)
	{
		syslog(LOG_ERR, "%s\n", "chdir");
		exit(1);
	}
	umask(0);
	for(i=0;i<MAXFILE;i++)
		close(i);
	if((fd=open("/tmp/dameon.log",O_CREAT|O_WRONLY|O_APPEND, 0600))<0)
	{
		syslog(LOG_ERR, "open");
		exit(1);
	}
	while(1)
	{
		write(fd, buf, len+1);
		sleep(10);
	}
	close(fd);
	closelog();
	exit(0);
}



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值