读书人

linux 管道 线程同步,该如何处理

发布时间: 2012-12-23 11:28:15 作者: rapoo

linux 管道 线程同步
各位,最近想使用管道来实现线程同步,出现一个问题,百思不得其解,望各位大侠指点一二...
先贴上代码:


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>



int pip[] = {-1, -1};


void sleep_select(int i)
{
struct timeval timeout;
timeout.tv_sec = i;
timeout.tv_usec = 0;
select(0, NULL, NULL, NULL, &timeout);
}

static void *threadFunction(void* userdata)
{
char data[5] = {0};
fd_set fds;
struct timeval timeout = {1,0};
int ret;

FD_ZERO(&fds);
FD_SET(pip[0], &fds);

printf("p0: %d\n", pip[0]);
printf("p1: %d\n", pip[1]);

while (1)
{
ret = select(pip[0] + 1, &fds, NULL, NULL, &timeout);
if (ret < 0)
{
printf("select error\n");
break;
}
else if (ret == 0)
{
//printf("no fd ready\n");
continue;
}
else
{
if (FD_ISSET(pip[0], &fds) > 0)
{
read(pip[0], data, 5);
printf("data: %s\n", data);
}
}
}

}

void *mysignal()
{
printf("signal\n");
char data[] = "data";
while (1)
{
sleep_select(2);
//printf("sowelflsdfsldfsdlfsdl\n");
write(pip[1], data, 5);
}
}

int main(int argc, char* argv[])
{
char data[] = "data";
pthread_t id;

if (pipe(pip)) {
printf("pipe error\n");
exit(-1);


}
printf("p0: %d\n", pip[0]);
printf("p1: %d\n", pip[1]);

if (pthread_create(&id, NULL, threadFunction, NULL))
{
printf("create thread error\n");
exit(-1);
}
printf("pthread id = %u\n", id);
pthread_create(&id, NULL, mysignal, NULL);
//signal(SIGUSR1, mysignal);


while (1)
{
sleep_select(2);
//sleep(2);
//write(pip[1], data, 5);
}

pthread_join(id, NULL);
}



这个程序中,主线程创建两个线程,一个线程向管道的写端写入数据,另一个线程监听管道的读端,当如果有数据到来时,读线程从管道中读出数据并打印。。


问题来了: 首先当我在写线程中,不用sleep()函数时,读端能监听到管道符的变化,当我用上sleep函数时,读端就监听不到管道符的变化了,我想知道这是为什么。。。。sleep()函数会影响管道符吗。。。。。
[最优解释]
哦,shit,需要把timeout的赋值移到while内!

#include <unistd.h>
#include <sys/time.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
//#include <fcntl.h>



int pip[2] = {-1, -1};


void sleep_select(int i)
{
struct timeval timeout;
timeout.tv_sec = i;
timeout.tv_usec = 0;
select(0, NULL, NULL, NULL, &timeout);
}

static void *threadFunction(void* userdata)
{
char data[6] = {0};
fd_set fds;
struct timeval timeout;

int ret;

FD_ZERO(&fds);
FD_SET(pip[0], &fds);

printf("p0: %d\n", pip[0]);
printf("p1: %d\n", pip[1]);

int counter = 0;

while (1)
{
timeout.tv_sec = 5;
timeout.tv_usec = 0;
//FD_ZERO(&fds);
FD_SET(pip[0], &fds);

ret = select(pip[0]+1, &fds, NULL, NULL, &timeout);
if (ret == -1)
{
printf("select error\n");
break;
}
else if (ret > 0)
{
if (FD_ISSET(pip[0], &fds))
{


read(pip[0], data, 5);
printf("data: %s\n", data);
printf("%s: %d, [%s]\n", __FUNCTION__, counter++, strerror(errno));
}
}
else
{
printf("no fd ready\n");
}
}

return NULL;

}

void *mysignal()
{
printf("signal\n");
char data[] = "data";
int counter = 0;
while (1)
{
sleep_select(2);
//sleep(2);
//printf("sowelflsdfsldfsdlfsdl\n");
write(pip[1], data, 5);
printf("time:%lu,%s: %d, [%s]\n", time(NULL), __FUNCTION__, counter++, strerror(errno));
}
}

int main(int argc, char* argv[])
{
pthread_t id;

if (pipe(pip))
{
printf("pipe error\n");
exit(-1);
}
printf("p0: %d\n", pip[0]);
printf("p1: %d\n", pip[1]);

//fcntl(pip[0], F_SETFL, fcntl(pip[0], F_GETFL, 0)
[其他解释]
请仔细看select的说明,select会修改timeout值的。
[其他解释]
应该是write端sleep的时候,read端的select认为没有writer了,所以立即返回0了。
[其他解释]

引用:
应该是write端sleep的时候,read端的select认为没有writer了,所以立即返回0了。

我最开始也是这样觉得,可是当用sleep后,read端的select是一直返回0,即便是当写端已经写入数据后,读端还是会返回0.这个sleep到底影响了一些什么东西。。。
[其他解释]
sleep()/select()都会造成进程里所有的线程休眠,所以你的mysignal线程里的sleep会影响到threadFunction的select,select会发现每次都超时了

threadFunction--select sleep 1秒
mysignal sleep 2秒(threadFunction线程一样会受影响多休眠2秒)
threadFunction-select发现已经是3秒超时了,所以返回0

你应该用pthread_cond_wait在mysignal线程里对线程休眠



[其他解释]
引用:
sleep()/select()都会造成进程里所有的线程休眠,所以你的mysignal线程里的sleep会影响到threadFunction的select,select会发现每次都超时了

threadFunction--select sleep 1秒
mysignal sleep 2秒(threadFunction线程一样会受影响多休眠2秒)
threadFun……


你好,我开始试过,在主线程中select/sleep都不会造成子线程休眠,在线程中的休眠也是独立的,好像不会影响到其他的线程的
------其他解决方案--------------------


我发现两个问题,一是 struct timeval timeout = {1,0}; 这行代码不对,二是,把这行代码修改对之后,超时超时还是不起作用,如果设置无限阻塞,则可以达到预期效果。
就是说,把timeout正确初始化之后,设置的超时不起作用,导致狂打 "no fd ready\n"
[其他解释]
O_NONBLOCK);
//fcntl(pip[1], F_SETFL, fcntl(pip[1], F_GETFL, 0)
[其他解释]
O_NONBLOCK);

if (pthread_create(&id, NULL, threadFunction, NULL))
{
printf("create thread error\n");
exit(-1);
}
printf("pthread id = %lu\n", id);
pthread_create(&id, NULL, mysignal, NULL);
//signal(SIGUSR1, mysignal);


while (1)
{
sleep_select(2);
//sleep(2);
//write(pip[1], data, 5);
}

pthread_join(id, NULL);
}


[其他解释]
heartlesstoanyone,高手,正解,select的实现不太合理。

读书人网 >UNIXLINUX

热点推荐