我在一个线程中生成“事件”结构,并以几秒的间隔将它们发送回主线程。自然是不行的。我有两个问题:
- 为什么在我的选择循环中收到大量事件接收消息?我是否需要从管道中读取,以便文件描述符不再说那里有东西?
- 如何从管道中提取对结构的引用?
期望的输出:
$ ...
Writing event 1 to pipe
Received event on pipe
Writing event 2 to pipe
Received event on pipe
实际输出:
$ ...
Received event on pipe
Received event on pipe
Received event on pipe
Received event on pipe
Received event on pipe
Received event on pipe
Received event on pipe
Received event on pipe
Received event on pipe
Received event on pipe
Received event on pipe
Received event o^C
GCC 命令:
gcc -o test test.c
测试.c:
/* Simple example with two threads and a pipe. One thread writes structs to a
pipe every few seconds; the other reads the structs, prints out their info
and then frees the structs
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/select.h>
void mywait(int timeInSec);
// The events
typedef struct event {
int id;
int data;
} event_t;
int id = 0;
int pipefd[2];
void* pump(void *arg) { // Generates events
for (;;)
{
mywait(1); // sleep thread
printf("writing event #%i to pipe\n", id);
// generate event
event_t *event;
event = malloc(sizeof(*event));
memset(event, 0, sizeof(*event));
event->id = id++;
// write event to pipe
write(pipefd[1], &event, sizeof(event));
// NOTE: Free event in other thread
}
}
int main (int argc, char **argv)
{
printf("Starting pipe_test.c\n");
// 1. Create a pipe
pipe(pipefd);
// 2. Create thread to pump events into pipe
pthread_t tid;
if (pthread_create( &tid, NULL, pump, NULL) != 0) {
perror("pthread_create:pump");
exit(-1);
}
// 3. Set up selector in main thread to read events off pipe
int z;
fd_set readfds; //readable file descriptor
int selectmax;
selectmax = pipefd[0] + 1;
for (;;)
{
// Initialize selector
FD_ZERO( &readfds );
FD_SET( pipefd[0], &readfds );
z = select( selectmax, &readfds, NULL, NULL, NULL );
if( z < 0 ) {
printf( "select() failed\n");
// close( pipefd ); //???
return 1;
} else {
if( FD_ISSET( pipefd[0], &readfds ) ) {
printf("Received event on pipe\n"); // I get a shitton of these
// Get the pointer to the event struct from the pipe
// TODO: GOOD WAY TO DO THIS?
// Free the struct
// TODO
}
}
}
return 0;
}
// From http://somethingswhichidintknow.blogspot.com/2009/09/sleep-in-pthread.html
pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;
void mywait(int timeInSec)
{
struct timespec timeToWait;
struct timeval now;
int rt;
gettimeofday(&now,NULL);
timeToWait.tv_sec = now.tv_sec + timeInSec;
timeToWait.tv_nsec = now.tv_usec*1000;
pthread_mutex_lock(&fakeMutex);
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
pthread_mutex_unlock(&fakeMutex);
}