linux相关函数,linux学习-信号相关函数
未決:在信號(hào)產(chǎn)生和遞送之間的時(shí)間間隔內(nèi),我們稱信號(hào)是未決的。
阻塞信號(hào)遞送:如果為進(jìn)程產(chǎn)生了一個(gè)阻塞信號(hào),而且對(duì)該信號(hào)的動(dòng)作是默認(rèn)動(dòng)作或捕捉該信號(hào),則為該進(jìn)程將此信號(hào)保持為未決的,直到進(jìn)程對(duì)此信號(hào)解除阻塞,或者對(duì)此信號(hào)的動(dòng)作更改為忽略。
信號(hào)屏蔽字:每個(gè)進(jìn)程都有一個(gè)信號(hào)屏蔽字,它規(guī)定了當(dāng)前要阻塞遞送到該進(jìn)程的信號(hào)集。
信號(hào)集:可以表示多個(gè)信號(hào)的數(shù)據(jù)類(lèi)型,定義數(shù)據(jù)類(lèi)型為sigset_t
#includeint sigemptyset(sigset_t *set); //初始化信號(hào)集為空
int sigfillset(sigset_t *set); //初始化信號(hào)集包括所有信號(hào)
int sigaddset(sigset_t *set,int signo); // 將信號(hào)signo加入到set信號(hào)集
int sigdelset(sigset_t *set,int signo); //將信號(hào)signo從信號(hào)集中刪除
1.函數(shù)kill和raise
#includeint kill(pid_t pid,int signo);
int raise(int signo);
返回值: 成功返回0,失敗返回-1
kill的pid參數(shù)
pid>0 將該信號(hào)發(fā)送進(jìn)程ID為pid的進(jìn)程
pid==0 將信號(hào)發(fā)送給與發(fā)送進(jìn)程同一進(jìn)程組的所有進(jìn)程,但不包 括系統(tǒng)進(jìn)程集,既內(nèi)核進(jìn)程和init。
pid<0 將該進(jìn)程發(fā)送給其他進(jìn)程組ID為pid絕對(duì)值的所有進(jìn)程,不包括系統(tǒng)進(jìn)程集
pid==-1將該信號(hào)發(fā)送給進(jìn)程有權(quán)限向它們發(fā)送信號(hào)的所有進(jìn)程,不包括系統(tǒng)進(jìn)程集
如上所述,進(jìn)程發(fā)送信號(hào)是要權(quán)限的,超級(jí)用戶可以發(fā)送給所有的進(jìn)程。非超級(jí)的,發(fā)送者的實(shí)際用戶ID或者有效用戶ID必須等于接收者的實(shí)際用戶ID或者有效用戶ID。
2.函數(shù)alarm和pause
alarm函數(shù)可以設(shè)置一個(gè)鬧鐘時(shí)間,超時(shí)產(chǎn)生SIGALRM信號(hào)。如忽略或者不捕捉該信號(hào),系統(tǒng)默認(rèn)動(dòng)作是終止調(diào)用alarm函數(shù)的進(jìn)程。
#includeunsigned int alarm(unsigned int seconds);
返回值:0,或者是以前設(shè)置的鬧鐘時(shí)間的剩余時(shí)間
每個(gè)進(jìn)程只能有一個(gè)鬧鐘時(shí)間。如果在調(diào)用alarm之前已經(jīng)為該進(jìn)程注冊(cè)的鬧鐘時(shí)間還未超時(shí),則該鬧鐘的剩余時(shí)間作為本次alarm函數(shù)調(diào)用的值返回。以前注冊(cè)的鬧鐘時(shí)間則被新值代替。如果本次調(diào)用的seconds值是0,則取消以前的鬧鐘,其剩余值,作為alarm函數(shù)的返回值。
pause函數(shù)調(diào)用進(jìn)程掛起,直到捕捉到一個(gè)信號(hào)
#includeint paush(void);
返回值:-1;errno設(shè)置為EINTR
給出一個(gè)用alarm和pause實(shí)現(xiàn)sleep的實(shí)例
#include#include#include#includestatic jmp_buf env_alrm;
static void myalrm(int signo) //信號(hào)處理函數(shù)
{
longjmp(env_alrm,1); //局部跳轉(zhuǎn)
}
int mysleep(int sec)
{
int minsec,ret,tmp=0;
if(signal(SIGALRM,myalrm)==SIG_EER)
return sec;
minsec=alrm(0); //得到上一次未超時(shí)定時(shí)器所剩的時(shí)間
ret=sec>minsec?(sec-minsec):0;
if(setjmp(env_alrm)==0) //局部跳轉(zhuǎn)
{
if(minsec) //考慮之前設(shè)置了定時(shí)器
alarm(minsecsec){ //若前面登記的定時(shí)器比睡眠時(shí)間長(zhǎng),退出后需要復(fù)位之前定時(shí)器剩下的時(shí)間
alarm(minsec-sec);
}
if(tmp)
ret+=tmp;
return ret;
}
int main()
{
int othersec;
alarm(6);
othersec=mysleep(3);
printf("return %d\n",othersec);
return 0;
}
3.函數(shù)sigprocmask
調(diào)用函數(shù)sigprocmask可以檢測(cè)和更改當(dāng)前阻塞而不能遞送給進(jìn)程的信號(hào)集。
#includeint sigprocmask(int how,const sigset_t *restrict set,sigset_t *restrict oset);
返回值:成功返回0,失敗返回-1;
若oset為非空指針,進(jìn)程當(dāng)前的信號(hào)屏蔽子通過(guò)oset返回。
若set為非空指針,參數(shù)how指示進(jìn)行何種操作。若為空,則不改變當(dāng)前信號(hào)屏蔽字,how參數(shù)也無(wú)用。
how
說(shuō)明
SIG_BLOCK
新set中的信號(hào)加到信號(hào)屏蔽字中
SIG_UNBLOCK
將set中信號(hào)從當(dāng)前信號(hào)屏蔽子中取出
SIG_SETMASK
該進(jìn)程新的信號(hào)屏蔽是set指向的值
4.函數(shù)sigismember
函數(shù)sigismember用來(lái)測(cè)試參數(shù)signum 代表的信號(hào)是否已加入至參數(shù)set信號(hào)集里。
int sigismember(const sigset_t *set,int signum)
返回值:有該信號(hào),返回1,無(wú)則返回0;出錯(cuò)返回-1
5.函數(shù)sigpending
sigpending函數(shù)返回在送往進(jìn)程的時(shí)候被阻塞掛起的信號(hào)集合。這個(gè)信號(hào)集合通過(guò)參數(shù)set返回。
#includeint sigpengding(sigset_t *set);
返回值:成功返回0,出錯(cuò)返回-1
下面這個(gè)例程,用到了上面幾個(gè)函數(shù)
static void sig_quit(int signo)
{
printf("caught sigquit\n");
}
int main()
{
sigset_t newmak,oldmask,pendmsk;
if(signal(SIGQUIT,sig_quit)==SIG_ERR)
printf("can not catch quit\n");
sigemptyset(&newmask); //信號(hào)集清空函數(shù)
sigaddmask(&newmask,SIGQUIT); //將信號(hào)添加到信號(hào)集中
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0) //將信號(hào)SIGQUIT添加到信號(hào)屏蔽字中
printf("err\n");
sleep(5);
if(sigpending(&pendmask)<0) //檢測(cè)當(dāng)前進(jìn)程中阻塞的信號(hào),通過(guò)pendmask返回
printf("sigpending err\n");
if(sigismember(&pendmask,SIGQUIT)) //檢測(cè)SIGQUIT是否在pendmask信號(hào)集中
printf("sigquit pending\n");
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0) //將SIGQUIT信號(hào)取消屏蔽
printf("err\n");
sleep(5);
exit(0);
}
6.函數(shù)sigaction
sigaction函數(shù)的功能是檢查或者修改與指定信號(hào)相關(guān)聯(lián)的動(dòng)作。此函數(shù)取代了早期使用的signal函數(shù)。
#includeint sigaction(int signo,conststruct sigaction*restrict act,
struct sigaction*restrict oact);
返回值:成功返回0,失敗返回-1
給信號(hào)signo設(shè)置新的信號(hào)處理函數(shù)act, 同時(shí)保留該信號(hào)原有的信號(hào)處理函數(shù)oldact。
此函數(shù)用到了一個(gè)數(shù)據(jù)結(jié)構(gòu)
struct sigaction{
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flag;
void (*sa_sigaction)(int,siginfo_t*,void*);
};
sa_handler字段:包含一個(gè)信號(hào)捕捉函數(shù)的地址。
sa_mask字段:說(shuō)明了一個(gè)信號(hào)集,在調(diào)用該信號(hào)捕捉函數(shù)之前,這一信號(hào)集要加進(jìn)進(jìn)程的信號(hào)屏蔽字中。僅當(dāng)從信號(hào)捕捉函數(shù)返回時(shí)再將進(jìn)程的信號(hào)屏蔽字復(fù)位為原先值。
sa_flags字段:指定對(duì)信號(hào)進(jìn)行處理的 各個(gè)選項(xiàng)。有張表格,我就不列了,自己百度吧。簡(jiǎn)單說(shuō)明下面程序用到的兩個(gè)標(biāo)志
SA_NODEFER: 當(dāng)信號(hào)處理函數(shù)正在進(jìn)行時(shí),不堵塞對(duì)于信號(hào)處理函數(shù)自身信號(hào)功能。
SA_RESETHAND:當(dāng)用戶注冊(cè)的信號(hào)處理函數(shù)被執(zhí)行過(guò)一次后,該信號(hào)的處理函數(shù)被設(shè)為系統(tǒng)默認(rèn)的處理函數(shù)。
sa_sigaction字段:是一個(gè)替代的信號(hào)處理程序,當(dāng)sa_flags 為SA_SIGINFO時(shí),使用該信號(hào)處理程序。sa_sigaction和sa_handler,應(yīng)用只能一次調(diào)用其中一個(gè)。
static void sig_quit(int signo)
{
printf("catch quit\n");
}
int main()
{
struct sigaction act,oldact;
act.sa_handler = sig_quit;
act.sa_flags = SA_NODEFER | SA_RESETHAND;
sigaction(SIGINT,&act,&oldact);
sleep(5);
printf("hello \n");
return 0;
}
7.函數(shù)sigsuspend
sigsuspend函數(shù)和pause函數(shù)一樣,可以使進(jìn)程掛起(進(jìn)入睡眠狀態(tài)),直至有信號(hào)發(fā)生。
sigsuspend函數(shù)的參數(shù)是一個(gè)信號(hào)集,這個(gè)信號(hào)集是用來(lái)屏蔽信號(hào)的,信號(hào)集中存放了要屏蔽的信號(hào)。
如果該信號(hào)集為空的話,sigsuspend就不屏蔽任何信號(hào),任何信號(hào)都可以使進(jìn)程從掛起狀態(tài)喚醒,這就與pause函數(shù)一樣了。
#includeint sigsuspend(const sigset_t *sigmask);
返回值:-1,并將errno設(shè)置為EINTR
可以用于保護(hù)代碼臨界區(qū),使其不被特定的信號(hào)中斷
#include#include#include#include#include#include#include#include#include#include#include#include#includestatic void sig_init(int);
int main()
{
sigset_t newmask,oldmask,waitmask;
printf("hello");
if(signal(SIGINT,sig_init)==SIG_ERR)
perror("signal");
sigemptyset(&waitmask);
sigaddset(&waitmask,SIGUSR1);
sigemptyset(&newmask);
sigaddset(&newmask,SIGINT);
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0) //將SIGINT加入到信號(hào)屏蔽字中,以oldmask返回
perror("sigprocmask");
printf("ok");
if(sigsuspend(&waitmask)!=-1) //將sigusr1屏蔽
perror("sigsuspend");
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0) //將阻塞信號(hào)SIGINT恢復(fù)
perror("sigprocmask");
exit(0);
}
static void sig_init(int signo)
{
printf("how are you\n");
}
總結(jié)
以上是生活随笔為你收集整理的linux相关函数,linux学习-信号相关函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux拷贝文件到多个目录,怎么在 L
- 下一篇: linux 64位 安装qt creat