私が考えることができる最も移植性の高いソリューションは次のとおりです。
pipe()
リーダーとライターの 2 つの FD を構築するために使用します。read()
あなたのループにリーダーを渡してください。リーダーを終了する必要がある人にライターを渡します。
- 読み取りスレッドから使用
select()
して、stdin とリーダー パイプの両方が読み取り可能になるのを待ちます。
- stdin が読み取り可能になったら、文字を読み取って処理し、ループを再開します。
- リーダー パイプが読み取り可能になったら、それを閉じてループを終了します。
ここで、パイプのもう一方の端を閉じるだけで、リーダー スレッドが起動し、select()
終了します。
従来のアプローチにはシグナルの使用が含まれますが、このパイプベースのソリューションでは、stdin での入力をチェックしたり、同じポーリング メカニズムを使用して終了する必要があるかどうかをチェックしたりできます。
getchar()
と の混合select()
は機能しないことに注意してください。これは、getchar()
が内部で効果的に使用fread()
され、 で実行されるバッファリングにより、利用可能なデータがあってもブロックされるfread()
可能性があるためです。代わりにselect()
使用してください。read()
これは、このアプローチをテストするために使用したプログラムの例です。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/select.h>
void * entry_point(void * p) {
int readpipe = *(int *)p;
fd_set rfds;
char c;
for (;;) {
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
FD_SET(readpipe, &rfds);
while (select(readpipe + 1, &rfds, NULL, NULL, NULL) == 0);
if (FD_ISSET(readpipe, &rfds)) {
close(readpipe);
break;
}
if (FD_ISSET(STDIN_FILENO, &rfds)) {
if (read(STDIN_FILENO, &c, sizeof(c)) > 0) {
printf("Read: %d\n", c);
}
}
}
printf("Thread terminating\n");
pthread_exit(NULL);
}
int main() {
pthread_t thread;
int r;
int pipes[2];
pipe(pipes);
if (r = pthread_create(&thread, NULL, entry_point, &pipes[0])) {
printf("Error: %d\n", r);
return 1;
}
sleep(5);
printf("Closing pipe and joining thread.\n");
close(pipes[1]);
pthread_join(thread, NULL);
pthread_exit(NULL);
}
実行例:
$ time ./test
1
Read: 49
Read: 10
2
Read: 50
Read: 10
3
Read: 51
Read: 10
4
Read: 52
Read: 10
5
Read: 53
Read: 10
Closing pipe and joining thread.
Thread terminating
real 0m5.004s
user 0m0.004s
sys 0m0.000s