コンテキスト切り替えがどのように機能するか、および特定のシグナルを受信した後にプロセスがコンテキストを切り替える方法を学ぼうとしています。これが私のコードです
#include<stdio.h>
#include<stdlib.h>
#include<ucontext.h>
#include<signal.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
#define STACK_SIZE 4096
static ucontext_t thread1, thread2;
void thread1_fun() {
static int a = 1;
while (1) {
printf("calling thread1 for %d time\n", a);
sleep(5);
a > 20 ? a = 0 : a++;
}
}
void thread2_fun() {
static int a = 1;
while (1) {
printf("calling thread2 for %d time\n", a);
sleep(5);
a > 20 ? a = 0 : a++;
}
}
void sig_handler(int signal) {
static int curr_thread = 0;
printf("received signal %d\n", signal);
if (curr_thread == 1) {
curr_thread = 0;
printf("switching from thread1 to thread2\n");
setcontext(&thread1);
} else {
curr_thread = 1;
printf("switching from thread2 to thread1\n");
setcontext(&thread2);
}
}
int main() {
int i = 0;
struct sigaction act;
act.sa_handler = sig_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGUSR1, &act, NULL);
/* sigaction(SIGTERM, &act, NULL); */
getcontext(&thread1);
thread1.uc_stack.ss_sp = malloc (STACK_SIZE);
thread1.uc_stack.ss_size = STACK_SIZE;
thread1.uc_stack.ss_flags = 0;
makecontext(&thread1, thread1_fun, 0);
getcontext(&thread2);
thread2.uc_stack.ss_sp = malloc (STACK_SIZE);
thread2.uc_stack.ss_size = STACK_SIZE;
thread2.uc_stack.ss_flags = 0;
makecontext(&thread2, thread2_fun, 0);
printf("%d\n", getpid());
while (1);
}
ここで、ターミナルから「kill -s SIGUSR1」コマンドを実行します。プロセスは、このシグナルを受信した後にコンテキストを切り替えますが、問題は、'calling thread for %d time'を 2 回出力することです。
たとえば、スレッド 1 が ' calling thread1 for 3rd time ' を出力してスリープ状態になり、スレッド 1 がスリープしている間にシグナルを送信してコンテキストを切り替えると、スレッド 2 が実行を開始し、もう一度シグナルを送信してコンテキストを切り替えると、スレッド 1 が再び「calling thread1」を出力する場合3回目」。理想的には、スリープ状態から抜け出し、a の値をインクリメントする必要がありますね。同じ値を 2 回出力するのはなぜですか?
コードで印刷された出力は次のとおりです。
受信信号 10
スレッド 2 からスレッド 1 への切り替え
thread2 を 1 回呼び出す
受信信号 10
スレッド 1 からスレッド 2 への切り替え
スレッド1を1回呼び出す
受信信号 10
スレッド 2 からスレッド 1 への切り替え
thread2 を 1 回呼び出す
受信信号 10
スレッド 1 からスレッド 2 への切り替え
スレッド1を1回呼び出す
これで私を助けてください。