目前分類:Linux singal (信號) (15)

瀏覽方式: 標題列表 簡短摘要
測試程式範例說明:
  1. 每個 thread 都先變更信號處理程序,再設定一個計時器,之後再 sleep 15 秒,就結束執行。
  2. 主要 thread 會先變更信號處理程序,再建立子 threads,之後再設定一個計時器,最後等待子 threads 結束。
#include 
#include 
#include 
#include 
#define NUMTHREADS 3

void sighand2(int signo)
{
    pthread_t tid = pthread_self();
    printf("a.Thread %lu in signal handler \n", tid);
    return;
}

void *threadfunc(void *parm)
{
    pthread_t tid = pthread_self();
    struct sigaction actions;
    struct itimerval itv;
    int rc;

    memset(&actions, 0, sizeof(actions));
    sigemptyset(&actions.sa_mask);
    actions.sa_flags = 0;
    actions.sa_handler = sighand;
    rc = sigaction(SIGALRM,&actions,NULL);

    itv.it_interval.tv_sec = (tid & 0xf) + 1;
    itv.it_interval.tv_usec = 0;
    itv.it_value = itv.it_interval;
    setitimer(ITIMER_REAL, &itv, NULL);
    printf("start time=%ld\n", time(NULL));

    printf("Thread %u(%x) entered\n", tid, tid);
    rc = sleep(15);
    if (rc != 0) {
        printf("Thread %u did not get expected results! rc=%d,%ld\n", tid, rc, time(NULL));
        pthread_exit(NULL);
    }
    printf("Thread %lu completed masked work\n", tid);
    pthread_exit(NULL);
}
void sighand(int signo)
{
    pthread_t tid = pthread_self();
    printf("Thread %lu in signal handler \n", tid);
    return;
}

int main(int argc, char **argv)
{
    int i, rc;
    struct itimerval itv;
    struct sigaction actions;
    pthread_t threads[NUMTHREADS];

    printf("Enter Testcase - %s\n", argv[0]);
    printf("Set up the alarm handler for the process\n");
    memset(&actions, 0, sizeof(actions));
    sigemptyset(&actions.sa_mask);
    actions.sa_flags = 0;
    actions.sa_handler = sighand;
    sigaction(SIGALRM,&actions,NULL);

    printf("Create unmasked threads\n");
    for(i=0; i
使用 NPTL on i386 結果說明:
  1. main thread 跟 child threads 的定時器共用,也就是只有一個可以用。
  2. main thread 定時 2s,child threads 定時 1s,如果 main thread 先跑,則定時器為會改回 1s,如下結果跑了 15 次 alarm。
  3. main thread 跟 child threads 的 signal 共用,也就是只有一個可以用。
  4. 當信號觸發時,會依照 thread 生成時間來決定執行的 thread,如下結果所示,都是由 main thread 來執行。
  5. threads 的 pid 都一樣,符合 POSIX 規定。
  6. 信號處理函數共用,後設定的會覆蓋掉原設定的值。
Enter Testcase - ./a.out
Set up the alarm handler for the process
Create unmasked threads
Wait for unmasked threads to complete
start time=1242723595
Thread 3086281616(b7f4eb90), pid=25624 entered
start time=1242723595
Thread 3075791760(b754db90), pid=25624 entered
start time=1242723595
Thread 3065301904(b6b4cb90), pid=25624 entered
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
a.Thread 3086284480 in signal handler 
Thread 3086281616 completed masked work
a.Thread 3086284480 in signal handler 
Thread 3075791760 completed masked work
Thread 3065301904 completed masked work
Main completed
使用 LinuxThreads on arm7 結果說明:
  1. 所有 threads 的定時器各自獨立,不會互相干擾。
  2. 所有 threads 的信號接受各自獨立,不會互相干擾。
  3. threads 的 pid 都不同,不符合 POSIX 規定。
  4. 信號處理函數共用,後設定的會覆蓋掉原設定的值。
Enter Testcase - ./aa
Set up the alarm handler for the process
Create unmasked threads
start time=1242781260
Thread 1026(402), pid=218 entered
start time=1242781260
Thread 2051(803), pid=219 entered
Wait for unmasked threads to complete
start time=1242781260
Thread 3076(c04), pid=220 entered
a.Thread 1024 in signal handler
a.Thread 1026 in signal handler
Thread 1026 did not get expected results! rc=12,1242781263
a.Thread 1024 in signal handler
a.Thread 2051 in signal handler
Thread 2051 did not get expected results! rc=11,1242781264
a.Thread 3076 in signal handler
Thread 3076 did not get expected results! rc=10,1242781265
Main completed

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

就跟傳統的 process 一樣,每個 thread 都有一個 signal mask,用來指定那些非同步 signal 會被 thread 處理,稱為 unblocked signals,那些 signal 不會被 thread 處理,稱為 blocked signals。根據 kernel 的設計,child process 中的第一個 thread 會繼承 parent process 中呼叫 fork 的 thread 的 signal mask,其它 thread 則會繼承呼叫 pthread_create 的 thread 的 signal mask。然後在 thread 再利用 pthread_sigmask 來調整 signal 是 blocked or unblocked。

當一個非同步產生的 signal 送達某個 process 時,它將由 process 中某個 thread 來處理,系統將會根據每個 thread 的 signal mask 來決定誰是選中的 thread 。如果有超過一個以上的 thread,它們的 signal mask 對 signal 來說都是 unblocked,系統將任意的幫你選一個。雖然你可以經由設定 signal mask 來影響系統選 thread 的過程,但無法直接指定某個 thread 來處理某個指定的 signal。

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

#include 

struct sched_param {
    int sched_priority;
};

int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
int sched_getscheduler(pid_t pid);
policy 參數
  1. SCHED_FIFO(First In-First Out)
    SCHED_FIFO 顧名思義就是『先進先出(First In First Out)』,一但 Procees 是 FIFO 模式,在被 Kernel 的排程器設為可運行時,將會立即先佔並插隊執行,比同樣系統優先權的其他『一般 Process』還優先,除非有系統優先權比較高的 Process 正在佔用時間,否則 FIFO Process 通常都會優先佔用。

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

#include 
int nice(int inc);

#include 
#include 
int getpriority(int which, int who);
int setpriority(int which, int who, int prio);
which, who 參數
  1. PRIO_PROCESS:who 參數指定 process ID,傳回或設定 process 的 priority。
  2. PRIO_PGRP:who 參數指定 process group ID,傳回或設定 process group 的 priority。
  3. PRIO_USER:who 參數指定 user ID,傳回或設定 user 的 priority 。
注意事項
  1. nice 值範圍 -20~19,每個行程預設值為 0,nice 值越高,priority 越低,也就是 -20 high priority,19 low priority。
  2. nice 值的不同只是代表行程分配的執行時間長短,跟優先權沒有關係。
  3. nice() 函數是把目前的 nice 值再加上 inc 值,而 setpriority() 的 prio 是直接取代 nice 值。
  4. nice() 是為了相容舊版函數,已經被 setpriority() 給取代了。
下面演示 setpriority() 範例,在沒有 setpriority() 的狀態下,大約 500 秒失敗退出,在有 setpriority() 的狀態下,大約 4210 秒失敗退出。
#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[])
{
    int pid=getpid();
    time_t tm1, tm2;
    sigset_t block;
    struct itimerval itv;

    sigemptyset(&block);
    sigaddset(&block, SIGALRM);
    sigprocmask(SIG_BLOCK, &block, NULL);

    itv.it_interval.tv_sec = 2;
    itv.it_interval.tv_usec = 0;
    itv.it_value = itv.it_interval;
    setitimer(ITIMER_REAL, &itv, NULL);

    tm1 = time(&tm1);
    while (1) {
        tm2 = time(&tm2);
        if (tm2 & 1) break;
        printf("%ld\n", tm2);
        setpriority(PRIO_PROCESS, pid, -20);
        sigwaitinfo(&block, NULL);
        setpriority(PRIO_PROCESS, pid, 0);
    }

    printf("start time = %ld\n", tm1);
    return 0;
}

part 3: http://jyhshin.pixnet.net/blog/post/27784046


台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

行程類型
  1. SCHED_FIFO
    一個先進先出的的即時行程,當排程器把 CPU 指派給該行程時,會把他當前位址的行程描述器收到 runqueue 串列,如果沒有其他優先權更高的即時行程是可執行的,則此行程會使用 CPU 直到他釋放為止,即使有其他行程擁有相同的優先權。
  2. SCHED_RR

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

#include 
#include 

int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
int timer_delete(timer timer_id);
int timer_getoverrun(timer_t timerid);
int timer_gettime(timer_t timerid, struct itimerspec *value);
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue);

typedef struct sigevent {
    int sigev_notify;
    int sigev_signo;
    sigval_t sigev_value;
    union {
        int _pad[SIGEV_PAD_SIZE];
        int _tid;
        struct {
            void (*_function)(sigval_t);
            pthread_attr_t *_attribute;
        } _sigev_thread;
    } _sigev_un;
} sigevent_t;

struct timespec {
    time_t tv_sec;
    long   tv_nsec;
};

struct itimerspec {
    struct timespec it_interval;
    struct timespec it_value;
};
sigev_notify 設定為如下值來定制計時器到期後的行為
  1. SIGEV_NONE
    什麼都不做,只提供通過 timer_gettime 和 timer_getoverrun 查詢超時資訊。
  2. SIGEV_SIGNAL

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

#include 

int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);

struct itimerval {
    struct timeval it_interval; /* next value */
    struct timeval it_value;    /* current value */
};
struct timeval {
    long tv_sec;                /* seconds */
    long tv_usec;               /* microseconds */
};
setitimer 比 alarm 強大很多,依照 which 值的不同,可同時產生三種不同類型的計時器。
  1. ITIMER_REAL
    依據系統真實的時間來計算,送出 SIGALRM(14) 信號。
  2. ITIMER_VIRTUAL

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

Linux 的定時器主要是用來解決需要定時執行某項工作時的應用。一般來說有三種方法可以使用:
  1. unsigned int alarm(unsigned int seconds);
    useconds_t ualarm(useconds_t usecs, useconds_t interval);
  2. int getitimer(int which, struct itimerval *value);

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

信號生命週期

  1. 信號誕生
  2. 信號在目標程序中註冊
  3. 信號在目標程序中註銷
  4. 信號結束

一、信號誕生

信號誕生指的是觸發信號的事件發生,比如檢測到硬體異常、計時器超時、呼叫信號發送函數 kill 等。

二、信號在目標程序中註冊

in kernel/include/linux/sched.h
struct task_struct {
...
    sigset_t blocked;
    struct sigpending pending;
...
};

in kernel/include/linux/signal.h
struct sigqueue {
    struct sigqueue *next;
    siginfo_t info;
};

struct sigpending {
    struct sigqueue *head, **tail;
    sigset_t signal;
};

在每一個程序中的 task_struct 結構裏,存在一個關於本程序中未處理信號的資料成員 struct sigpending pending。struct sigpending 中的 sigset_t signal 代表程序中所有未處理的信號集合,*head, **tail 分別指向一個 struct sigqueue 的結構鏈首尾,struct sigqueue 稱之為未處理信號資訊鏈。

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

來源:http://www.bccn.net/Article/kfyy/vc/jszl/200708/5850_2.html

实例二:信号传递附加信息

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

來源:http://www.bccn.net/Article/kfyy/vc/jszl/200708/5850.html

一、信号生命周期

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

來源:http://www.bccn.net/Article/kfyy/vc/jszl/200708/5849_2.html

五、信号的安装(设置信号关联动作)

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

來源:http://www.bccn.net/Article/kfyy/vc/jszl/200708/5849.html

 

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

早期不可靠的信號處理函數

void (*signal(int signo, void (*func)(int))) (int);
int raise(int signo);
unsigned int alarm(unsigned int seconds);
int pause(void);
void abort(void);
不可靠的原因
  1. 在信號發生之後到信號處理程式中調用 signal 函數之間有一段時間空窗期。在此段時間中,可能發生另一次中斷信號。第二個信號會造成執行默認動作,而對中斷信號則是終止該進程。
  2. 在進程不希望某種信號發生時,它不能關閉該信號。進程能做的就是忽略該信號。有時希望通知系統“阻止下列信號發生,如果它們確實產生了,請記住它們。“
  3. 如果在進程執行一個低速系統調用而阻塞期間捕捉到一個信號,則該系統調用就被中斷不再繼續執行。該系統調用返回出錯,其 errno 設置為 EINTR。

POSIX 1003.1 信號處理函數

int kill(pid_t pid, int signo);
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
int sigfillset(sigset_t *set);
int sigemptyset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);
int sigpending(sigset_t *set);
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
int sigsuspend(const sigset_t *sigmask);

POSIX 1003.1b 信號處理函數

int sigqueue (pid_t pid, int sig, const union sigval val);
int sigwaitinfo(const sigset_t *set, siginfo_t *info);
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout);

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://bigwhite.blogbus.com/logs/1453143.html

台南小新 發表在 痞客邦 PIXNET 留言(1) 人氣()