❶ linux中自己用sigaction函數重新實現signal函數為什麼可行,而不報錯不是
信號是與一定的進程相聯系的。也就是說,一個進程可以決定在進程中對哪些信號進行什麼樣的處理。例如,一個進程可以忽略某些信號而只處理其他一些信號;另外,一個進程還可以選擇如何處理信號。總之,這些總與特定的進程相聯系的。因此,首先要建立其信號和進程的對應關系,這就是信號的安裝登記。
Linux主要有兩個函數實現信號的安裝登記:signal和sigaction。其中signal在系統調用的基礎上實現,是庫函數。它只有兩個參數,不支持信號傳遞信息,主要是用於前32個非實時信號的安裝;而sigaction是較新的函數(由兩個系統調用實現:sys_signal以及sys_rt_sigaction),有三個參數,支持信號傳遞信息,主要用來與sigqueue系統調用配合使用。當然,sigaction同樣支持非實時信號的安裝,sigaction優於signal主要體現在支持信號帶有參數。
對於應用程序自行處理的信號來說,信號的生命周期要經過信號的安裝登記、信號集操作、信號的發送和信號的處理四個階段。信號的安裝登記指的是在應用程序中,安裝對此信號的處理方法。信號集操作的作用是用於對指定的一個或多個信號進行信號屏蔽,此階段對有些應用程序來說並不需要。信號的發送指的是發送信號,可以通過硬體(如在終端上按下Ctrl-C)發送的信號和軟體(如通過kill函數)發送的信號。信號的處理指的是操作系統對接收信號進程的處理,處理方法是先檢查信號集操作函數是否對此信號進行屏蔽,如果沒有屏蔽,操作系統將按信號安裝函數中登記注冊的處理函數完成對此進程的處理。
❷ linux用戶空間 - 多進程編程(三)
管道用於有學園關系的進程之間。
管道的pipe 系統調用實際上就是創建出來兩個文件描述符。
當父進P1程創建出 fd[2] 時,子進程P2 會繼承父進程的所有,所以也會得到pipe 的 2個 文件描述符。
所以毫無瓜葛的兩個進程,一定不會訪問到彼此的pipe。無法用管道進行通信。
管道一般是單工的。f[0]讀,f[1]寫
管道也可以適用於 兄弟進程(只要有血緣即可)。由於管道是單工的,當兩個進程之間需要雙向通信,則需要兩跟管道。
執行
ctrl-c(2號信號) + SIGUSR1 信號 綁了一個新函數。則 ctrl-c 無效。
查看進程的信號
號信號被捕獲。
將2號信號忽略掉
9號信號 kill 和19號信號 stop 不能亂搞,只能用預設。
其它信號甚至段信號也都可以捕獲。
改變程序的執行現場,修改PC指針,有些像goto,只不過返回非0值
運行結果
making segment fault
after segment fault
程序不會死。
如果不忽略 page fault
則會產生 core mp.
不停的給data 賦值,同時每隔1s會有信號進來,列印 data的值。
理論上列印出來的結果同時為0,同時為1
但並非如此,是 0,1,交替隨機的。
signal 非同步的,隨時都可以進來,所以列印出來的結果,並不是我想要的。
信號對於應用程序來說,很像中斷對於內核,都是訪問臨界區數據
信號被屏蔽,延後執行。
寫多線程的程序時,不要以為只有線程之間有競爭,其實信號也會有競爭
system v 的IPC 年代有些久遠。
有血緣關系的進程 key_t 都是相同的。
Key 是私有key IPV PRIVATE
可能用消息隊列,可能用共享內存,可能用信號量進行通訊。
利用 _pathname 路徑,約定好一條路徑。和tcp/ip地址很像,來生成一個key_t key, 用msg_get shm_get 得到共享內存or 信號量。
int id 可以理解為文件描述符 fd。
其中Sys V 的共享內存 最為常用。
一定要檢查路徑,如果僅僅有2個進程,你沒有創建路徑,兩者都是 -1(相當於大家約定好了),那當然能通信拉。但更多的進程出現,則會有問題。
一定要檢查返回值
依然依靠key,但是api 實在是太挫了。P&V 操作都是 semop. (posix 的 ipc跟為簡潔)
POSIX 共享內存當然也需要一個名字,但並不是路徑。
無論讀進程還是寫進程,都需要傳入相同的名字。
如果是unbuntu 會在以下路徑生成文件
其實 2和3 是1 的符號鏈接。 只要保證是一個就能互相通信
關鍵點,mmap 內存的屬性修改為 private 後,產生寫時,虛擬地址一樣,但是物理地址已經不同了
當然 如果子進程修改了程序背景,執行了 exec,那麼完全不一樣了,直接修改了內存邏輯。
❸ Linux中同步信號和非同步信號分別怎麼解釋
Linux非同步信號
1.int pthread_kill(pthread_t threadid, intsigno);
向特定的線程發送信號signo
2.int pthread_sigmask(int how, const sigset_t*newmask, sigset_t *oldmask);
設置線程的信號屏蔽碼
3.int sigwait(const sigset_t *set, int *sig);
阻塞線程,等待set中指定的信號之一到達,並將到達的信號存入*sig。
4.代碼
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
//#define SIGUSRR 40;
int SIGUSRR = 40;
void* threadOne(void *arg)
{
sigset_tsigset;
intsigno;
sigemptyset(&sigset);
sigaddset(&sigset,SIGUSRR);
pthread_sigmask(SIG_BLOCK,&sigset, NULL);
while(1)
{
sigwait(&sigset,&signo);
printf("getthread cond sig!\n");
}
}
int main(int argc, char **argv)
{
if(argc != 1)
{
printf("Usage:\n");
printf("threadcond\n");
return1;
}
pthread_tthreadId;
if(pthread_create(&threadId,NULL, threadOne, NULL) != 0)
{
printf("threadcreate error! \n");
return1;
}
//structsigaction act;
//act.sa_handler=SIG_IGN;
//sigemptyset(&act.sa_mask);
//act.sa_flags=0;
//sigaction(SIGUSRR,&act,0);//設置信號SIGUSR1的處理方式忽略
usleep(1000000);
pthread_kill(threadId,SIGUSRR);
usleep(1000000);
pthread_kill(threadId,SIGUSRR);
usleep(2000000);
return0;
}
❹ linux 內核中斷 用什麼鎖
首先我闡明一下,用鎖的情況只有兩種:
線程
文件
內核程序在使用的時候也脫離不了這兩種鎖的概念。
中斷,是信號,是否要處理中斷信號?或者產生中斷信號?
對信號來說只有:
信號屏蔽、信號捕捉、信號排隊、可重如函數等概念。
你想問的問題,我沒猜測,在處理某個信號時,不想讓其他信號中斷,那麼使用信號屏蔽字:
先設置要屏蔽的信號集,要保存的信號集,初始信號集,可供協調使用的函數有幾個:
#include <signal.h>
signal(這個不建議使用,應為有些老的實現是有問題的),設置信號處理程序
sig_atomic_t 數據類型
sigprocmask,設置信號屏蔽字
sigaction,設置信號處理程序,功能跟強悍,可控性更好
sigsuspend,以原子性方式,等待某些信號發生,然後返回
你具體要做啥不清楚,但使用上面的信號相關的函數,肯定能實現你的功能。參考APUE的論述。