Windows XP Windows 7 Windows 2003 Windows Vista Windows教程綜合 Linux 系統教程
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟件教程
 Windows教程網 >> Linux系統教程 >> Linux教程 >> linux 信號

linux 信號

日期:2017/2/7 14:42:10      編輯:Linux教程
 

1. 信號處理函數為多個線程共享。

2. 線程的私有信號在該線程被調度的時候傳遞(信號處理函數被處理)

pthread_kill()本質上調用tkill(), tgkill().

兩個例子說明上述情況:

1. 信號處理函數為多個線程共享。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

class Prep_Test {
public:
Prep_Test() {
cancel_flag = 0;
id = 0;
};
static void* prepWrapper(void* args);
int cancel_flag;
pthread_t id;
};

class State_Test {
public:
State_Test() {
cancel_flag = 0;
id = 0;
};
static void* stateWrapper(void* args);
int cancel_flag;
pthread_t id;
};

class SIG_HANDLER {
public:
SIG_HANDLER() {
prepID[0] = 0;
prepID[1] = 0;
prepID[2] = 0;
stateID = 0;
};
Prep_Test prepTest[3];
State_Test stateTest;
pthread_t prepID[3];
pthread_t stateID;
};

SIG_HANDLER sigHandler;

void sighandler(int signo) {
pthread_t id = pthread_self();
printf("sighandler state thread id = %lu\n", id);
sigHandler.stateTest.cancel_flag = true;
}

void sighandler2(int signo) {
pthread_t id = pthread_self();
printf("sighandler prep thread id = %lu\n", id);
if (signo = SIGTERM) {
for (int i = 0; i < 3; i++) {
if (id == sigHandler.prepID[i]) {
sigHandler.prepTest[i].cancel_flag = true;
}
}
}
}

void * Prep_Test::prepWrapper(void* args) {
int rc;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
Prep_Test * p = (Prep_Test *)args;
if (p == NULL) return NULL;

struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = sighandler2;

rc = sigaction(SIGTERM, &actions, NULL);
printf("install prep sig action rc = %d\n", rc);

while(!(p->cancel_flag)) {

printf("prep thread %lu before sleep\n", pthread_self());
int rc = 0;//sleep(5);
printf("prep thread %lu after sleep %d\n", pthread_self(), rc);
}
printf("prep thread %lu exit\n", pthread_self());
p->cancel_flag = false;
return NULL;
}

void * State_Test::stateWrapper(void* args) {
int rc;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
State_Test * p = (State_Test *)args;
if (p == NULL) return NULL;

struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = sighandler;

rc = sigaction(SIGTERM, &actions, NULL);
printf("install state sig action rc = %d\n", rc);

while(!(p->cancel_flag)) {
printf("state thread %lu before sleep\n", pthread_self());
int rc = 0;//sleep(5);
printf("state thread %lu after sleep %d\n", pthread_self(), rc);
}
printf("state thread %lu exit\n", pthread_self());
p->cancel_flag = false;
return NULL;
}

int main() {
int rc;

rc = pthread_create(&(sigHandler.stateID), NULL, State_Test::stateWrapper, &(sigHandler.stateTest));
printf("create state thread rc = %d, id = %lu\n", rc, sigHandler.stateID);
 

rc = pthread_create(&(sigHandler.prepID[0]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[0]));
printf("create prep 0 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[0]);

rc = pthread_create(&(sigHandler.prepID[1]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[1]));
printf("create prep 1 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[1]);

rc = pthread_create(&(sigHandler.prepID[2]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[2]));
printf("create prep 2 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[2]);

sleep(3);
printf("___________________________\n");
printf("cancel state id = %lu\n", sigHandler.stateID);
pthread_kill(sigHandler.stateID, SIGTERM);
printf("brfore main sleep\n");
sleep(2);
printf("after main sleep\n");

return 0;
}
 



在運行之後, state線程的信號處理函數變成了prep線程的信號處理函數, 可見被替換, 只有一個信號處理函數。





2. 線程的私有信號在該線程被調度的時候傳遞(信號處理函數被處理)

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

class Prep_Test {
public:
Prep_Test() {
cancel_flag = 0;
id = 0;
};
static void* prepWrapper(void* args);
int cancel_flag;
pthread_t id;
};

void * Prep_Test::prepWrapper(void* args) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
Prep_Test * p = (Prep_Test *)args;
if (p == NULL) return NULL;

while(!(p->cancel_flag)) {

printf("prep thread %lu before sleep\n", pthread_self());
int rc = 0;//sleep(5);
printf("prep thread %lu after sleep %d\n", pthread_self(), rc);
}
printf("prep thread %lu exit\n", pthread_self());
p->cancel_flag = false;
return NULL;
}

class State_Test {
public:
State_Test() {
cancel_flag = 0;
id = 0;
};
static void* stateWrapper(void* args);
int cancel_flag;
pthread_t id;
};
 

void * State_Test::stateWrapper(void* args) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
State_Test * p = (State_Test *)args;
if (p == NULL) return NULL;

while(!(p->cancel_flag)) {
printf("state thread %lu before sleep\n", pthread_self());
int rc = 0;//sleep(5);
printf("state thread %lu after sleep %d\n", pthread_self(), rc);
}
printf("state thread %lu exit\n", pthread_self());
p->cancel_flag = false;
return NULL;
}

class SIG_HANDLER {
public:
SIG_HANDLER() {
prepID[0] = 0;
prepID[1] = 0;
prepID[2] = 0;
stateID = 0;
};
//static void sighandler(int signo);

Prep_Test prepTest[3];
State_Test stateTest;
pthread_t prepID[3];
pthread_t stateID;
};

SIG_HANDLER sigHandler;

void sighandler(int signo) {
pthread_t id = pthread_self();
printf("sighandler thread id = %lu\n", id);
if (signo = SIGTERM) {
if (id == sigHandler.stateID) {
sigHandler.stateTest.cancel_flag = true;
}
else {
for (int i = 0; i < 3; i++) {
if (id == sigHandler.prepID[i]) {
sigHandler.prepTest[i].cancel_flag = true;
}
}
}
}
}
 

int main() {
//Prep_Test prepTest[3];
//State_Test stateTest;
//pthread_t prepID[3];
//pthread_t stateID;
int rc;
//SIG_HANDLER sigHandler;
struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = sighandler;

rc = sigaction(SIGTERM, &actions, NULL);
printf("install sig action rc = %d\n", rc);

rc = pthread_create(&(sigHandler.stateID), NULL, State_Test::stateWrapper, &(sigHandler.stateTest));
printf("create state thread rc = %d, id = %lu\n", rc, sigHandler.stateID);
 

rc = pthread_create(&(sigHandler.prepID[0]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[0]));
printf("create prep 0 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[0]);

rc = pthread_create(&(sigHandler.prepID[1]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[1]));
printf("create prep 1 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[1]);

rc = pthread_create(&(sigHandler.prepID[2]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[2]));
printf("create prep 2 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[2]);

sleep(3);
printf("___________________________\n");
printf("cancel state id = %lu\n", sigHandler.stateID);
pthread_kill(sigHandler.stateID, SIGTERM);
/*
printf("cancel prep0 id = %lu\n", sigHandler.prepID[0]);
pthread_kill(sigHandler.prepID[0], SIGTERM);
printf("cancel prep1 id = %lu\n", sigHandler.prepID[1]);
pthread_kill(sigHandler.prepID[1], SIGTERM);
printf("cancel prep2 id = %lu\n", sigHandler.prepID[2]);
pthread_kill(sigHandler.prepID[2], SIGTERM);
*/
printf("brfore main sleep\n");
sleep(2);
printf("after main sleep\n");

return 0;
}
 

經多次測試, 沒有發現這個信號被其它線程相應的情況。
 

Copyright © Windows教程網 All Rights Reserved