Linux中的信號
kill -9 pid #kill只是起到發送信號的作用,-9參數纔是殺死進程
ctrl+c相當於kill 2 pid
3和9不可被捕捉替換
信號可做兩個進程之間的通訊,同步,而不是發送數據
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGURG 23
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGIO 29
#define SIGPOLL SIGIO
/*
#define SIGLOST 29
*/
#define SIGPWR 30
#define SIGSYS 31
/* signal 31 is no longer "unused", but the SIGUNUSED macro remains for backwards compatibility */
#define SIGUNUSED 31
/* These should not be considered constants from userland. */
#define SIGRTMIN 32
#define SIGRTMAX _NSIG
//捕獲signum信號,重新定義這個信號的操作函數爲myfunc()
signal(int signum,myfunc());
signal(SIGINT,myfunc);
signal(SIGINT,SIG_IGN);//參數SIG_IGN表示忽略這個信號,但quite和kill信號無法屏蔽
如何發起異步操作
kill 命令 eg:kill -signum pid
int kill(pid,signum);
pid>0 發給pid進程
pid=0 發給當前進程組的所有進程(fork出來的進程)
pid=-1 發送給所有進程
pid<0 發送給|PID|所對應的組上
pid=getpid()
gpid=getgpid()
raise
自舉信號,會給自己發送一個信號
int raise(int sig);
int kill(getpid(),signum);
alarm
定時函數
unsigned int alarm(unsigned int seconds);
函數會在所指定的seconds之後收到SIGALRM信號
signal(SIGALRM,printf);
alarm(2);
第二次設置alarm時,會立即返回上次未消耗地時間
ualarm
useconds_t ualarm(useconds_t usecs, useconds_t interval);
以useconds爲單位,第一個參數爲第一次產生時間,第二個參數爲間隔產生
setitimer 定時器
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
Linux會給進程提供三個定時器
ITIMER_REAL:以逝去時間遞減
ITIMER_VIRTUAL:
struct itimerval {
struct timeval it_interval; /* next value */
struct timeval it_value; /* current value */
};
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
信號可能會打斷阻塞函數,可以用來做超時響應
因爲信號可能打斷accept阻塞,所以還要判斷一次錯誤類型,如果是打斷,則重新accept
獲取文件大小方法
sigaction對象
在早期,signal(int signum,myfunc());沒有設計得比較周全,只能給綁定的函數傳入一個信號類型的參數,所以後期纔有了sigaction對象
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
struct sigaction
{ //兩個函數指針只調用其一,通過sa_flags設置
void (*sa_handler)(int);//若調用此,和普通signal函數沒區別
//信號類型,發射信號時當前進程系統信息結構體(如下),給sa_handler傳的參數,通過sigqueue方法發送
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;//信號屏蔽集
int sa_flags; //會影響信號接受特殊標誌,可設置爲0(只調用sa_handler)和SA_SIGINFO(調用sa_sigaction)
void (*sa_restorer)(void);
};
siginfo_t {
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal */
void *si_ptr; /* POSIX.1b signal */
int si_overrun; /* Timer overrun count; POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault */
long si_band; /* Band event (was int in
glibc 2.3.2 and earlier) */
int si_fd; /* File descriptor */
short si_addr_lsb; /* Least significant bit of address
(since Linux 2.6.32) */
}
- 信號會喚醒當前進程的阻塞狀態
sigqueue
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<string.h>
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("arguments error!");
exit(0);
}
pid_t pid=atoi(argv[1]);//將進程號轉化爲整數
union sigval v;
v.sival_int=100;
//這兒只是利用SIGINT來發送數據,
//任何信號都行,只需要發送端與接收端規定一致即可
sigqueue(pid,SIGINT,v);//給一pid發送信號和void *參數
return 0;
}
sigval_t
union sigval {
int sival_int;
void *sival_ptr;
};
信號集合
信號集是爲了方便批量設置屏蔽(不接收)各種信號,SIG_IGN是忽略(接收不處理)
用位圖的形式(如一個int有32位)存儲信號
- sigset_t sa_mas
int sigemptyset(sigset_t *set);//清空
int sigfillset(sigset_t *set);//填充
int sigaddset(sigset_t *set, int signum);//給信號集添加信號
int sigdelset(sigset_t *set, int signum);//刪除
int sigismember(const sigset_t *set, int signum);//查找
設置信號屏蔽集合
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);//第三個參數用來做上一集合備份
第一個參數爲一下幾種
SIG_BLOCK//阻塞
SIG_UNBLOCK//非阻塞
SIG_SETMASK//屏蔽
未決信號
sigpending(sigset)用來獲取已接收的被屏蔽信號,若此信號解除屏蔽,會立即執行一次此信號的回調函數
int block
32bit
00000000000000000000000000000100
sigsuspend 函數 等待信號
阻塞接收所設置的信號,若接收了其他信號,則解除阻塞往下運行
int sigsuspend(const sigset_t *mask);
運用signal IO做socket觸發
要用fcntl給skcket綁定個PID,因爲signal需要通過PID發送
設置dev時儘量不要用 fcntl設置,用ioctl
參考
https://blog.csdn.net/freeking101/article/details/78338497