برنامه زیر ابتدا تمام سیگنالها را بلاک میکند و بعد به تعدادی که در خط فرمان مشخص کردهایم thread میسازد.
از طریق برنامه و با شیوهای که در نمونه خروجی نشان داده شده است میتوانیم سیگنال دلخواه را به thread دلخواه ارسال کنیم.
توجه کنید که SIGKILL و SIGSTOP قابل بلاک شدن نیستند و SIGCONT حتی در صورت بلاک بودن باز هم تحویل پروسس میشود (البته اگر این سیگنال بلاک شده باشد در لیست سیگنالهای pending میماند و سیگنال هندلر آن اجرا نمیشود تا زمانی که سیگنال را از حالت بلاک خارج کنیم).
سیگنال SIGUSR1 برای پیادهسازی برنامه مورد استفاده قرار گرفته است و به همین خاطر قابل ارسال به thread ها نیست.
برنامه باید با کتابخانه pthread لینک شود. طریقه کامپایل به صورت زیر است.
$ gcc file.c -lpthread
/** * Thread signal sending. * * Mohsen safari * mstafreshi.ir */ #include <stdio.h> #include <stdlib.h> #include <err.h> #include <pthread.h> #include <string.h> #include <signal.h> #include <unistd.h> struct { int index; pthread_t tid; } *thread; void sigusr1Handler(int sig) { } void exitEN(int s, char *str) { if (str != NULL) fprintf(stderr, "%s: ", str); fprintf(stderr, "%s\n", strerror(s)); exit(s); } void * threadFunc(void *arg) { sigset_t mask; int i, j, count, id; id = *((int *) arg); for(;;) { sigemptyset(&mask); if (sigpending(&mask) == -1) { fprintf(stderr, "sigpending"); pthread_exit(NULL); } for (j = 1; j < NSIG; j++) { if (sigismember(&mask, j)) { count = 1; printf("====== [thread %d] ======\n", id + 1); for (i = j ; i < NSIG; i++) { if (sigismember(&mask, i)) { printf("%d- %s (%d)\n", count, strsignal(i), i); count++; } } break; } } pause(); } } int main(int argc, char *argv[]) { int s, thrNum, sigNum, thrCount; char buf[BUFSIZ]; struct sigaction sa; sigset_t mask; pthread_t recvThr; if (argc != 2) { fprintf(stderr, "usage: %s threads-count\n", argv[0]); exit(EXIT_FAILURE); } thrCount = atoi(argv[1]); if (thrCount < 1) errx(EXIT_FAILURE, "threads-count must be at leaset 1"); thread = calloc(thrCount, sizeof(*thread)); if (thread == NULL) err(EXIT_FAILURE, "calloc"); sigfillset(&mask); sigdelset(&mask, SIGQUIT); sigdelset(&mask, SIGUSR1); sigemptyset(&sa.sa_mask); sa.sa_handler = sigusr1Handler; if (sigaction(SIGUSR1, &sa, NULL) == -1) err(EXIT_FAILURE, "sigaction"); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(EXIT_FAILURE, "procsigmask"); for (int j = 0; j < thrCount; j++) { thread[j].index = j; s = pthread_create(&thread[j].tid, NULL, threadFunc, &thread[j].index); if (s != 0) exitEN(s, "pthread_create"); } while (1) { if (fgets(buf, BUFSIZ, stdin) == NULL) break; if (buf[0] == '\n') { fprintf(stderr, "usage: sig thread-number sig-number\n"); continue; } if (sscanf(buf, "sig %d %d", &thrNum, &sigNum) != 2) { warnx("invalid data"); continue; } if (thrNum < 1 || thrNum > thrCount) { warnx("invalid thread-num: %d", thrNum); continue; } if (sigNum < 0 || sigNum >= NSIG) { warnx("invalid sig-num: %d", sigNum); continue; } if (sigNum == SIGUSR1) { warnx("SIGUSR1 is in use. Not allwed for user!"); continue; } if (pthread_kill(thread[thrNum - 1].tid, sigNum) == -1) warn("pthread_kill"); if (pthread_kill(thread[thrNum - 1].tid, SIGUSR1) == -1) warn("pthread_kill-SIGUSR1"); } exit(EXIT_SUCCESS); }
نمونه خروجی برنامه به صورت زیر است:
$ ./a.out 7 sig 7 1 ====== [thread 7] ====== 1- Hangup (1) sig 7 2 ====== [thread 7] ====== 1- Hangup (1) 2- Interrupt (2) sig 7 4 ====== [thread 7] ====== 1- Hangup (1) 2- Interrupt (2) 3- Illegal instruction (4) sig 1 7 ====== [thread 1] ====== 1- Bus error (7) sig 1 65 a.out: invalid sig-num: 65 sig 1 8 ====== [thread 1] ====== 1- Bus error (7) 2- Floating point exception (8) sig 4 56 ====== [thread 4] ====== 1- Real-time signal 22 (56) sig 4 52 ====== [thread 4] ====== 1- Real-time signal 18 (52) 2- Real-time signal 22 (56)
کلیه حقوق برای دارندهی سایت محفوظ است.