linux信号值头文件位置,Linux C 信号处理机制
一 . 信號
1. 信號:是內核發送給某一進程的一種消息 。
2. 信號機制:是Linux系統中用于進程之間相互通信或操作的一種機制。
3. 信號的來源:信號來源于內核
4. 產生原因: (1)用戶通過終端輸入 (2)進程執行(3)一個進程調用kill向另一個進程發送信號
5. 信號分類:1)同步信號 ? ?異步信號
2)可靠信號 : 信號被遞送多次 ?不可靠信號: 只被遞送一次的信號
6. 信號處理方式
A.? 按系統默認方式處理 ——每個信號都有一個默認動作,典型的默認動作是終止進程。 man signal 7 列出系統對各信號的默認處理 。
B.? 忽略信號——接收信號,但是不做任何操作 。
C. ?捕捉信號——程序提前告訴內核,當信號到來時應該調用哪個函數。
二. 信號相關函數
1. ?簡單的信號處理
函數原型: sighandler_t signal(int signum, sighandler_t handler);
參 ? ?數:signum ——要響應的信號,handler ?——信號發生時要執行的操作。
返回值:非-1 ? ?執行成功,返回以前的信號處理函數指針
-1 ? ? ? ?遇到錯誤
//捕捉信號
#include
#include
#include
#include
void capture(int signum){
printf("SIGINT is capture!\n");
}
int main(int argc, char *argv[]){
int i=10;
if(signal(SIGINT,capture) == SIG_ERR){
printf("Can't catch SIGINT");
exit(1);
}
printf("waiting for signal...\n");
while(i > 0){
printf("Now i=%d \n",i);
sleep(1);
i--;
}
return 0;
}
//忽略信號
#include
#include
#include
int main(int argc,char *argv[]){
int i=10;
signal(SIGINT,SIG_IGN);
printf("waiting for signal ...\n");
while(i > 0){
sleep(1);
i--;
printf("Now i = %d,but you can't stop this program by Ctrl + C\n",i);
}
return 0;
}
//恢復信號的默認處理
#include
#include
void capthensfl(int signum){
printf("SIGINT is capture !\n");
signal(SIGINT,SIG_DFL);
printf("SIGINT now is defaulted !\n");
}
int main(int argc,char *argv[]){
int i=10;
signal(SIGINT,capthensfl);
printf("waiting for signal...\n");
while(i > 0){
sleep(1);
printf("Now i = %d\n",i);
i--;
}
return 0;
}
2. 信號處理函數:指定一個信號的處理函數
函數原型:int sigaction(int signum, struct sigaction *action, struct sigaction *oldaction);
參 ? ?數:signum ?,要處理的信號
action ? ? ? ?要安裝的信號處理操作的結構
oldaction ? 之前的信號處理操作的結構
返回值:0? ? 成功 ? ? -1,失敗
說 ? ?明:oldaction不為NULL,則用其來存儲以前設置的與此信號關聯的操作。
action不為NULL: 則指定信號關聯的操作為此參數指向的結構 否則,信號處理保持不變。(此方式用來查詢當前對指定信號的處理方式)
sigaction的結構:
struct sigaction{
union{ ?? ??? ?__sighandler_t _sa_handler;
void(*_sa_sigaction)(int , struct siginfo *, void *);
} __u;
sigset_t sa_mask;
unsigned long sa_flags;
};
sa_sigaction的說明: void (*sa_sigaction)(int, struct siginfo *,void *);
第一個參數:要響應的信號 。
第二個參數:記錄導致產生信號的原因、類型等 。
第三個參數:信號發生時被中斷的上下文環境 信號能傳遞簡單的信息。
//使用sa_sigaction類型函數
#include
#include
#include
#include
void fun(int signo, siginfo_t *info, void *context){
printf("Test for sa_sigaction !\n");
}
int main(int argc,char *argv[]){
struct sigaction action,oldaction;
sigemptyset(&action.sa_mask);
action.sa_flags=SA_SIGINFO;
action.sa_sigaction=fun;
sigaction(SIGINT,&action,&oldaction);
printf("waiting for signal...\n");
while(1){
pause();
}
return 0;
}
3.?初始化信號集
函數原型:int sigemptyset(sigset_t ?*set);
int sigfillset(sigset_t ?*set);
參 ? ?數:set ?待初始化的信號集
返回值:0? ?成功 ? ? -1,失敗
4.?添加、刪除信號
函數原型:int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
參 ? ?數:set ?待初始化的信號集 . ?signo ?待添加/刪除的信號編號
返回值:0? 成功 ? ? -1,失敗
5.?修改屏蔽信號集
函數原型:int sigprocmask(int how,sigset_t *set, sigset_t * oldset);
參 ? ?數:how ? 如何修改信號掩碼
set?要使用的信號集
oldset ? 之前的信號集
返回值:0? 成功 ? ? -1,失敗
對參數how的說明: ? ?SIG_BLOCK:信號集中增加set中的信號
SIG_UNBLOCK:信號集中刪除set中的信號
SIG_SETMASK:信號集被設置為set信號集
三. ?系統調用函數
1.?kill ?—— 向進程發送一個信號
函數原型:int kill(pid_t pid, int sig);
參 ? ?數:pid 目標進程id,?sig ?要發送的信號
返回值:0? 成功 ? ? -1,失敗
說 ? ?明: ? ? pid>0 ? ? ?目標進程的進程號為pid
pid=0 ? ? ?將信號發送給和當前進程在同一進程租的所有進程
pid=-1 ? ? 將信號發送給系統內的所有進程
pid<0 ? ? ?將信號發送給進程組號PGID為pid絕對值的所有進程
一個進程可使用kill函數將信號發送給另一進程或進程組。
要求:發送信號的進程的用戶ID和目標進程的用戶ID相同,或發送信號的進程的owner是一個超級用戶。
//kill 使用示例
#include
#include
#include
void fun(int signo){
printf("Process capture SIGINT");
signal(SIGINT,SIG_DFL);
}
int main(int argc,char *argv[]){
int pid;
if((pid=fork()) == -1){
perror("fork");
exit(EXIT_FAILURE);
}
else if( pid == 0){
signal(SIGINT,fun);
printf("Child %d waiting for parent %d send signal\n",getpid(),getppid());
pause();
pause();
}
else{
sleep(1);
printf("Parent %d will send signal to child %d \n",getppid(),getpid());
kill(pid,SIGINT);
wait(NULL);
}
return 0;
}
2.?raise ——?自舉一個信號
函數原型:int raise(int signo);
參 ? ?數:signo ? ? ?待發送的信號
返回值:0? 成功 ? ? -1,失敗
說 ? 明:raise(signo)=kill(getpid(),signo)
3.?alarm ——?設置計時器
函數原型:int alarm(int seconds);
參 ? ?數:seconds ?計時的秒數
返回值: ? ? ?0 ? ?之前未調用過alarm
>0 ? 之前調用alarm設置的鬧鐘時間的余留秒數
4.?pause ——?掛起調用進程
函數原型:int pause(void);
返回值:-1 ? ? ? 并將errno設置為EINTR
四. 信號集合操作應用示例
/* ?信號的應用示例:
父進程執行文件復制操作,如果收到SIGUSR1信號,就打印出當前的復制進度
子進程每隔一個固定時間向父進程發送SIGUSR1信號
*/
#include
#include
#include
#include
#include
#include
int count; ?//當前復制大小
int file_size; //文件的大小
//父進程對SIGUSR1信號的處理函數
void sig_usr(int signum){
float i;
//求出復制進程
i = (float)count/(float)file_size;
printf("current over : %0.0f%%\n",i*100);
}
//子進程對SIGUSR1信號的處理,即向父進程發送SIGUSR1信號
void sig_alarm(int signo){
kill(getppid(),SIGUSR1);
}
//主函數
int main(int argc ,char *argv[]){
pid_t pid;
int i;
int fd_src,fd_des;
char buf[128];
if(argc != 3){
printf("the format must be : command src_file des_file \n");
return -1;
}
//以只讀方式打開源文件
if((fd_src = open(argv[1],O_RDONLY)) == -1){
perror("open fd_src");
exit(EXIT_FAILURE);
}
//獲取源文件大小
file_size = lseek(fd_src,0,SEEK_END);
//重新設置讀寫位置為文件頭
lseek(fd_src,0,SEEK_SET);
//以讀寫方式打開目標文件,如果不存在就創建
if((fd_des = open(argv[2],O_RDWR|O_CREAT,0644)) == -1){
perror("open fd_des");
exit(EXIT_FAILURE);
}
//進程創建失敗
if((pid = fork() == -1)){
perror("fork");
exit(EXIT_FAILURE);
}
//父進程
else if(pid > 0){
//安裝信號
signal(SIGUSR1,sig_usr);
do{
memset(buf,'\0',128);
//復制數據
if((i = read(fd_src,buf,1)) == -1){
perror("read");
exit(EXIT_FAILURE);
}
//如果復制完成,向子進程發送SIGINT信號,終止
else if(i == 0){
kill(pid,SIGINT);
break;
}
else{
//執行復制操作
if(write(fd_des,buf,i) == -1){
perror("write");
exit(EXIT_FAILURE);
}
count += i; //更新已經復制的文件的大小
}
}while(i != 0);
//等待子進程退出
wait(pid,NULL,0);
exit(EXIT_SUCCESS);
}
//子進程
else if(pid == 0){
usleep(1);
signal(SIGALRM,sig_alarm);
ualarm(1,1);
while(i){
;
}
exit(EXIT_SUCCESS);
}
return 0;
}
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的linux信号值头文件位置,Linux C 信号处理机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hottray.exe是什么进程 有什么
- 下一篇: hptskmgr.exe是什么进程 作用