我在一个线程中生成“event”结构,并以几秒为间隔将它们发送回主线程。当然它不能正常工作。我有两个问题:
期望的输出:
$ ...
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
test.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);
}
答案 0 :(得分:1)
read
读取结构,就像使用write一样。还有其他几点:首先是实际发送指针的地址,而不是实际的指针。其次,您不必动态分配结构,只需在堆栈上分配并发送结构。
答案 1 :(得分:1)
正如其他人所指出的,你需要实际读取数据。另请注意,您需要为整个结构分配内存,而不仅仅是指针(即event = malloc(sizeof(event_t));
)。
/* 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/time.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 (;;)
{
printf("writing event #%i to pipe\n", id);
// generate event
event_t *event;
event = malloc(sizeof(event_t));
memset(event, 0, sizeof(event_t));
event->id = id++;
// write event to pipe
int nbytes = write(pipefd[1], &event, sizeof(event_t*));
//printf("written %d bytes.\n", nbytes);
// NOTE: Free event in other thread
mywait(1); // sleep 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
event_t* received_event = NULL;
int nbytes = read(pipefd[0], &received_event, sizeof(event_t*));
printf("read %d bytes\n", nbytes);
if (nbytes > 0)
printf("Event id: %d\n", received_event->id);
// Free the struct
free(received_event);
}
}
mywait(1); // sleep thread
}
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);
}
答案 2 :(得分:0)
select
仅告诉您有可用的数据。您必须read
数据才能将其从描述符中删除。我还建议您在调试中添加一些信息(至少是一个时间戳),以便您可以看到数据创建的广度:)