a.cpp
#include <sys/types.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <mutex>
#include <thread>
#include <map>
#include <random>
typedef void(*Handler_func)(int);
void sig_handler(int) {
}
int check_signal() {
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGTERM);
sigaddset(&ss, SIGUSR1);
timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 0;
int sig = sigtimedwait(&ss, nullptr, &ts);
if (sig > 0) {
return sig;
} else {
if (errno != EAGAIN) {
char buf[1024];
char *bufp = strerror_r(errno, buf, 1024);
printf("sigtimedwait fail. %s\n", bufp);
return -1;
}
}
return 0;
}
int set_sigprocmask() {
sigset_t newss;
sigemptyset(&newss);
sigaddset(&newss, SIGCHLD);
sigaddset(&newss, SIGUSR1);
sigaddset(&newss, SIGALRM);
sigaddset(&newss, SIGHUP);
sigaddset(&newss, SIGINT);
sigaddset(&newss, SIGQUIT);
sigaddset(&newss, SIGTERM);
if (sigprocmask(SIG_BLOCK, &newss, nullptr)) {
return 1;
} else {
return 0;
}
}
int set_sigaction(int sig, Handler_func func) {
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = func;
sigemptyset(&sa.sa_mask);
if (sigaction(sig, &sa, nullptr)) {
return 1;
} else {
return 0;
}
}
int set_sigaction_ign(int sig) {
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
if (sigaction(sig, &sa, nullptr)) {
return 1;
} else {
return 0;
}
}
int init_signal() {
set_sigaction(SIGCHLD, &sig_handler);
set_sigaction(SIGUSR1, &sig_handler);
set_sigaction(SIGALRM, &sig_handler);
set_sigaction(SIGHUP, &sig_handler);
set_sigaction(SIGINT, &sig_handler);
set_sigaction(SIGQUIT, &sig_handler);
set_sigaction(SIGTERM, &sig_handler);
set_sigaction_ign(SIGPIPE);
if (set_sigprocmask()) {
return 1;
} else {
return 0;
}
}
class th_info {
public:
std::thread th;
pthread_t main_pthread_t;
};
void thread_func(std::mutex &mtx, std::map<int, th_info> &ths, int num) {
//Stopps während der Produktion und Verarbeitung der Eltern
mtx.lock();
mtx.unlock();
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> wait_time(1, 10);
while (!check_signal()) {
sleep(wait_time(mt));
printf("[%d]: send SIGUSR1.\n", num);
mtx.lock();
pthread_kill(ths[num].main_pthread_t, SIGUSR1);
mtx.unlock();
}
}
void main_thread(std::mutex &mtx, std::map<int, th_info> &ths) {
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGHUP);
sigaddset(&ss, SIGTERM);
sigaddset(&ss, SIGINT);
sigaddset(&ss, SIGQUIT);
sigaddset(&ss, SIGUSR1);
while (1) {
int sig;
sigwait(&ss, &sig);
if (sig == SIGUSR1) {
printf("recv SIGUSR1.\n");
} else {
printf("recv FINISH SIGNAL.\n");
break;
}
}
//Sammle Subthreads
mtx.lock();
for (auto &it : ths) {
pthread_kill(it.second.th.native_handle(), SIGUSR1);
}
mtx.unlock();
for (auto &it : ths) {
it.second.th.join();
}
}
void gen_thread(std::mutex &mtx, std::map<int, th_info> &ths) {
pthread_t main_pthread_t = pthread_self();
mtx.lock();
for (int i = 0; i < 3; ++i) {
std::thread th(thread_func, std::ref(mtx), std::ref(ths), i);
ths[i].th = std::move(th);
ths[i].main_pthread_t = main_pthread_t;
}
mtx.unlock();
}
int main(int, char **) {
if (init_signal()) {
printf("init_signal fail.\n");
return 1;
}
std::mutex mtx;
std::map<int, th_info> ths;
gen_thread(mtx, ths);
main_thread(mtx, ths);
return 0;
}
[root@localhost ~]# g++ --std=c++11 a.cpp -lpthread [root@localhost ~]# [root@localhost ~]# ./a.out [1]: send SIGUSR1. recv SIGUSR1. [2]: send SIGUSR1. recv SIGUSR1. [0]: send SIGUSR1. recv SIGUSR1. [1]: send SIGUSR1. recv SIGUSR1. [2]: send SIGUSR1. recv SIGUSR1. [2]: send SIGUSR1. recv SIGUSR1. [0]: send SIGUSR1. recv SIGUSR1. ^Crecv FINISH SIGNAL. [1]: send SIGUSR1. [2]: send SIGUSR1. [0]: send SIGUSR1. [root@localhost ~]#
Führen Sie pthread_self () im Hauptthread aus, bevor Sie einen Thread erzeugen Sie können es speichern.
Wenn Sie den Haupt-Thread auf der Neben-Thread-Seite benachrichtigen möchten, pthread_kill(main_pthread_t, SIGUSR1); Sie können es so benachrichtigen.
Nachdem Sie den Handler im Voraus für signalbezogene Einstellungen eingestellt haben Wenn Sie es nicht blockieren, funktioniert es nicht.
Verwenden Sie zum Zeitpunkt der Erstellung eines Threads so oft wie möglich Sigwait usw. Verhindern Sie, dass der Handler funktioniert. (Am Ende des Programms schläft der Subthread also nur im Schlaf. Diese werden nicht durch Interrupt-Verarbeitung entfernt, warten Sie auf die Anzahl der verstrichenen Sekunden und beenden Sie dann)
Wenn Sie den Code vorerst zum Laufen bringen, wird er etwas lang ... Hmm.
Nachtrag vom 10.12.2015
Als ich die Operation beobachtete, als ich ein Signal an den Haupt-Thread sendete, Andere Threads erhalten ebenfalls ...
Nur der Haupt-Thread muss das Signal mit Sigwait abfangen. Wenn andere Threads mit Sigwait warten, Sowohl der Haupt-Thread als auch andere Threads werden von sigwait zurückgegeben ...
Hmmm, Subthread-> Entscheide das Signal, das separat an den Haupt-Thread gesendet werden soll. Dies ist eine Lösung, wenn Sie nicht auf das Signal auf der Subthread-Seite warten. ..
Ich frage mich, ob es schlauer ist und ich kein Signal nur an den Haupt-Thread senden kann.
Ich habe den Hauptthread pthread_t gespeichert, um ein Signal mit pthread_kill zu senden. Immerhin scheint es gleichbedeutend mit dem Prozess des Killens zu sein (pid des Hauptthreads, SIGUSR1);
Hmm.