首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

linux 管道 线程同步,该如何解决

2013-01-07 
linux 管道线程同步各位,最近想使用管道来实现线程同步,出现一个问题,百思不得其解,望各位大侠指点一二...

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) 
[解决办法]
 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);
}


[解决办法]
select 不仅会改变timeout的值,而且会改变fd_set集合的值。所以调用完一次select后,fd_set和timeout都必须重置...
曾经因为这问题搞了很久。

热点排行