Linux下read函数默认到底是阻塞的还是非阻塞的?

时间:2023-01-13 20:38:42
Unix网络编程那边书上说,read默认就是阻塞的,但我怎么在Linux2.6.25 fc9下感觉read()默认就是非阻塞的捏?
1. Linux下read函数默认到底是阻塞的还是非阻塞的?
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏?
谢谢大家!

21 个解决方案

#1


这个,实在open设备的时候指定的,给个非阻塞的例子:
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#define MSG_TRY "try again\n"

int main(void)
{
char buf[10];
int fd, n;
fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
if(fd<0) {
perror("open /dev/tty");
exit(1);
}
tryagain:
n = read(fd, buf, 10);
if (n < 0) {
if (errno == EAGAIN) {
sleep(1);
write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
goto tryagain;
}
perror("read /dev/tty");
exit(1);
}
write(STDOUT_FILENO, buf, n);
close(fd);
return 0;
}

无数据最好把线程挂起。

#2


Linux下线程的挂起和恢复

POSIX的Linux操作系统没有提供线程挂起和恢复的例程,在网上找了找,看到一个老外写的程序,感觉想法不错,放在这里大家分享一下。理论上应该可以实现,不过我没有试,给大家提供一个参考。
void CPrcThread<Worker>::suspend()
{
    ifdef WIN32
    //do windows specific things here... 
    #endif

    #ifdef __linux__
     pthread_mutex_lock(&mutex);
     flag--;
     pthread_mutex_unlock(&mutex);
    #endif
}

void CPrcThread<Worker>::resume()

        #ifdef WIN32
        //do windows specific things here... 
        #endif

        #ifdef __linux__
        pthread_mutex_lock(&mutex);
        flag++;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        #endif
}

void* CPrcThread<Worker>::threadFunc(void* pParameter)
{

     while(1)
    {

          #ifdef WIN32
        //do windows specific things here... 
        //no member variables accessed here so its ok...
        #endif


         #ifdef __linux__
           pthread_mutex_lock(&mutex);
           while(flag <= 0)
           {
                   pthread_cond_wait(&cond, &mutex);
           }
           pthread_mutex_unlock(&mutex); 
          #endif


          //actual thread work here

    }

}

#3


引用楼主 shmilyxbq 的帖子:
Unix网络编程那边书上说,read默认就是阻塞的,但我怎么在Linux2.6.25 fc9下感觉read()默认就是非阻塞的捏? 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 
谢谢大家!

楼主可以用select函数实现阻塞调用。具体select如何使用网上有很多的例子。

#4


都没有回答我的问题啊~我的问题很简单:
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 

#5


引用 3 楼 hdukg 的回复:
引用楼主 shmilyxbq 的帖子:

Unix网络编程那边书上说,read默认就是阻塞的,但我怎么在Linux2.6.25 fc9下感觉read()默认就是非阻塞的捏? 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 
谢谢大家! 

楼主可以用select函数实现阻塞调用。具体select如何使用网上有很多的例子。


我目前只有一个读入需求,想直接利用read的阻塞特性,select太复杂了

#6


阻塞的吧

#7


引用 5 楼 shmilyxbq 的回复:
引用 3 楼 hdukg 的回复:
引用楼主 shmilyxbq 的帖子: 

Unix网络编程那边书上说,read默认就是阻塞的,但我怎么在Linux2.6.25 fc9下感觉read()默认就是非阻塞的捏? 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 
谢谢大家! 

楼主可以用select函数实现阻塞调用。具体select如何使用网上有很多的例子。 



我目前只有一个读入需求,想直接利用read…

1、个人认为默认的应该是阻塞的。
2、如果你想阻塞读取,可以open的时候设置好参数,同时设置好VMIN和VTIME的值应该可以。

#8


在open的时候,如何显式地把设备描述符设置成read阻塞的呢?能不能直接写个例子,谢谢!

#9


引用 8 楼 shmilyxbq 的回复:
在open的时候,如何显式地把设备描述符设置成read阻塞的呢?能不能直接写个例子,谢谢!

在open的时候,如何显式地把打开的文件设置成read阻塞的呢?能不能直接写个例子,谢谢!

#10


引用 9 楼 shmilyxbq 的回复:
引用 8 楼 shmilyxbq 的回复:

在open的时候,如何显式地把设备描述符设置成read阻塞的呢?能不能直接写个例子,谢谢! 
在open的时候,如何显式地把打开的文件设置成read阻塞的呢?能不能直接写个例子,谢谢! 

那么在open的时候,如何显式地把打开的设备文件设置成read阻塞的呢?能不能直接写个例子,谢谢! 

#11


楼主很偏执,仔细看楼上的那些回答,不可能得不到答案。

你要的例子 在linux下打 man select 就可以得到例子。

#12


引用 11 楼 ido158 的回复:
楼主很偏执,仔细看楼上的那些回答,不可能得不到答案。 

你要的例子 在linux下打 man select 就可以得到例子。


还是得不到答案,请大家指点!谢谢

#13


引用 4 楼 shmilyxbq 的回复:
都没有回答我的问题啊~我的问题很简单: 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 


你在读什么东西时候判断是否阻塞?如果是块设备或者块设备上的文件,这些被定义为快速设备的对象,是无论如何都不会阻塞的;某些 char 设备、pipe, fifo, socket 等“慢速设备”在读写时候会阻塞。

#14



read函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket描述字,管道文件等,这些文件的缺省read都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl设置取消文件O_NOBLOCK状态,也会产生阻塞的read效果。

#15


引用 13 楼 Wolf0403 的回复:
引用 4 楼 shmilyxbq 的回复:

都没有回答我的问题啊~我的问题很简单: 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 


你在读什么东西时候判断是否阻塞?如果是块设备或者块设备上的文件,这些被定义为快速设备的对象,是无论如何都不会阻塞的;某些 char 设备、pipe, fifo, socket 等“慢速设备”在读写时候会阻塞。

我是在读一个FIFO的时候,想在open("/path/fifoname", O_RDONLY, 0);这一步把这个有名管道设置成阻塞的,
任何地方都说默认是阻塞的,但是我测试感觉是非阻塞的,数据没过来read()就返回了,总之没读到数据。
请问显式的改怎么做?如果显式的设置阻塞后仍然读不到数据,那我就把这个“阻塞”问题排除了,再看是不是其他地方出了问题,谢谢!

#16


源代码,不加错误信息捕捉。线程thread1();向线程thread2();发送一个字符串,线程thread2();收到后修改返回给thread1();,thread1();打印收到字符串。

#include <iostream>
#include <string.h> //strlen()
#include <fcntl.h> //O_WRONLY O_RDONLY
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h> //mkfifo()
#include <errno.h> //EEXIST

#define FIFOPATH1 "/home/xbq/dev/thread/fifo1"
#define FIFOPATH2 "/home/xbq/dev/thread/fifo2"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

using namespace std;

void* thread1 (void*)
{
int readfd, writefd;
char* buff = (char*)"nihao thread!";

writefd = open(FIFOPATH1, O_WRONLY, 0);
readfd = open(FIFOPATH2, O_RDONLY, 0);
int len = strlen(buff);

write(writefd, buff, len);
read(readfd, buff, 512);
cout << buff << "in thread1" << endl;
close(readfd);
close(writefd);
}

void* thread2 (void*)
{
int readfd, writefd, n;
char* buff;
buff = new char[15];

readfd = open(FIFOPATH1, O_RDONLY, 0);
writefd = open(FIFOPATH2, O_WRONLY, 0);

cout << read(readfd, buff, 13) << endl;
buff[strlen(buff)] = '\0';
cout << buff << "in thread2" << endl;
sprintf(buff, "%s%s", buff, "!!");
cout << buff << "in thread2" << endl;
write(writefd, buff, strlen(buff));

delete buff;
close(readfd);
close(writefd);
}

int main (void)
{
pthread_t tid1, tid2;
cout << pthread_self() << endl;
cout << mkfifo(FIFOPATH1, FILE_MODE);
cout << mkfifo(FIFOPATH2, FILE_MODE);

pthread_create(&tid1, NULL, thread1, NULL);
pthread_create(&tid2, NULL, thread2, NULL);

unlink(FIFOPATH1);
unlink(FIFOPATH2);
return 0;
}

#17


写一个线程一读,线程二写的简单例子试试。

#18


问题解决,结贴了!
由于本人的粗心大意,将源代码移动后忘记改变管道路径的宏定义:
#define FIFOPATH1 "/home/xbq/dev/thread/fifo1"
#define FIFOPATH2 "/home/xbq/dev/thread/fifo2"
由于我对Unix IO函数边界值不熟悉,所以程序中没有错误捕捉的代码,这也导致我没能及时发现这个低级错误!
踏踏实实,一步一个脚印地学习Unix编程!引以为戒

#19


引用 14 楼 billow_zhang 的回复:
read函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket描述字,管道文件等,这些文件的缺省read都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl设置取消文件O_NOBLOCK状态,也会产生阻塞的read效果。

详细~

#20


引用 14 楼 billow_zhang 的回复:
read函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket描述字,管道文件等,这些文件的缺省read都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl设置取消文件O_NOBLOCK状态,也会产生阻塞的read效果。


经典

#21


引用 20 楼 badboydw 的回复:
引用 14 楼 billow_zhang 的回复:
read函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket描述字,管道文件等,这些文件的缺省read都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl设置取消文件O_NOBLOCK状态,也会产生阻塞的read效果。


经典


确实经典,正在学习这块儿,今天把老帖子都翻出来了,看看,呵呵

#1


这个,实在open设备的时候指定的,给个非阻塞的例子:
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#define MSG_TRY "try again\n"

int main(void)
{
char buf[10];
int fd, n;
fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
if(fd<0) {
perror("open /dev/tty");
exit(1);
}
tryagain:
n = read(fd, buf, 10);
if (n < 0) {
if (errno == EAGAIN) {
sleep(1);
write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
goto tryagain;
}
perror("read /dev/tty");
exit(1);
}
write(STDOUT_FILENO, buf, n);
close(fd);
return 0;
}

无数据最好把线程挂起。

#2


Linux下线程的挂起和恢复

POSIX的Linux操作系统没有提供线程挂起和恢复的例程,在网上找了找,看到一个老外写的程序,感觉想法不错,放在这里大家分享一下。理论上应该可以实现,不过我没有试,给大家提供一个参考。
void CPrcThread<Worker>::suspend()
{
    ifdef WIN32
    //do windows specific things here... 
    #endif

    #ifdef __linux__
     pthread_mutex_lock(&mutex);
     flag--;
     pthread_mutex_unlock(&mutex);
    #endif
}

void CPrcThread<Worker>::resume()

        #ifdef WIN32
        //do windows specific things here... 
        #endif

        #ifdef __linux__
        pthread_mutex_lock(&mutex);
        flag++;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        #endif
}

void* CPrcThread<Worker>::threadFunc(void* pParameter)
{

     while(1)
    {

          #ifdef WIN32
        //do windows specific things here... 
        //no member variables accessed here so its ok...
        #endif


         #ifdef __linux__
           pthread_mutex_lock(&mutex);
           while(flag <= 0)
           {
                   pthread_cond_wait(&cond, &mutex);
           }
           pthread_mutex_unlock(&mutex); 
          #endif


          //actual thread work here

    }

}

#3


引用楼主 shmilyxbq 的帖子:
Unix网络编程那边书上说,read默认就是阻塞的,但我怎么在Linux2.6.25 fc9下感觉read()默认就是非阻塞的捏? 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 
谢谢大家!

楼主可以用select函数实现阻塞调用。具体select如何使用网上有很多的例子。

#4


都没有回答我的问题啊~我的问题很简单:
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 

#5


引用 3 楼 hdukg 的回复:
引用楼主 shmilyxbq 的帖子:

Unix网络编程那边书上说,read默认就是阻塞的,但我怎么在Linux2.6.25 fc9下感觉read()默认就是非阻塞的捏? 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 
谢谢大家! 

楼主可以用select函数实现阻塞调用。具体select如何使用网上有很多的例子。


我目前只有一个读入需求,想直接利用read的阻塞特性,select太复杂了

#6


阻塞的吧

#7


引用 5 楼 shmilyxbq 的回复:
引用 3 楼 hdukg 的回复:
引用楼主 shmilyxbq 的帖子: 

Unix网络编程那边书上说,read默认就是阻塞的,但我怎么在Linux2.6.25 fc9下感觉read()默认就是非阻塞的捏? 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 
谢谢大家! 

楼主可以用select函数实现阻塞调用。具体select如何使用网上有很多的例子。 



我目前只有一个读入需求,想直接利用read…

1、个人认为默认的应该是阻塞的。
2、如果你想阻塞读取,可以open的时候设置好参数,同时设置好VMIN和VTIME的值应该可以。

#8


在open的时候,如何显式地把设备描述符设置成read阻塞的呢?能不能直接写个例子,谢谢!

#9


引用 8 楼 shmilyxbq 的回复:
在open的时候,如何显式地把设备描述符设置成read阻塞的呢?能不能直接写个例子,谢谢!

在open的时候,如何显式地把打开的文件设置成read阻塞的呢?能不能直接写个例子,谢谢!

#10


引用 9 楼 shmilyxbq 的回复:
引用 8 楼 shmilyxbq 的回复:

在open的时候,如何显式地把设备描述符设置成read阻塞的呢?能不能直接写个例子,谢谢! 
在open的时候,如何显式地把打开的文件设置成read阻塞的呢?能不能直接写个例子,谢谢! 

那么在open的时候,如何显式地把打开的设备文件设置成read阻塞的呢?能不能直接写个例子,谢谢! 

#11


楼主很偏执,仔细看楼上的那些回答,不可能得不到答案。

你要的例子 在linux下打 man select 就可以得到例子。

#12


引用 11 楼 ido158 的回复:
楼主很偏执,仔细看楼上的那些回答,不可能得不到答案。 

你要的例子 在linux下打 man select 就可以得到例子。


还是得不到答案,请大家指点!谢谢

#13


引用 4 楼 shmilyxbq 的回复:
都没有回答我的问题啊~我的问题很简单: 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 


你在读什么东西时候判断是否阻塞?如果是块设备或者块设备上的文件,这些被定义为快速设备的对象,是无论如何都不会阻塞的;某些 char 设备、pipe, fifo, socket 等“慢速设备”在读写时候会阻塞。

#14



read函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket描述字,管道文件等,这些文件的缺省read都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl设置取消文件O_NOBLOCK状态,也会产生阻塞的read效果。

#15


引用 13 楼 Wolf0403 的回复:
引用 4 楼 shmilyxbq 的回复:

都没有回答我的问题啊~我的问题很简单: 
1. Linux下read函数默认到底是阻塞的还是非阻塞的? 
2. 怎样让read在无数据可读的时候阻塞调用进程/线程捏? 


你在读什么东西时候判断是否阻塞?如果是块设备或者块设备上的文件,这些被定义为快速设备的对象,是无论如何都不会阻塞的;某些 char 设备、pipe, fifo, socket 等“慢速设备”在读写时候会阻塞。

我是在读一个FIFO的时候,想在open("/path/fifoname", O_RDONLY, 0);这一步把这个有名管道设置成阻塞的,
任何地方都说默认是阻塞的,但是我测试感觉是非阻塞的,数据没过来read()就返回了,总之没读到数据。
请问显式的改怎么做?如果显式的设置阻塞后仍然读不到数据,那我就把这个“阻塞”问题排除了,再看是不是其他地方出了问题,谢谢!

#16


源代码,不加错误信息捕捉。线程thread1();向线程thread2();发送一个字符串,线程thread2();收到后修改返回给thread1();,thread1();打印收到字符串。

#include <iostream>
#include <string.h> //strlen()
#include <fcntl.h> //O_WRONLY O_RDONLY
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h> //mkfifo()
#include <errno.h> //EEXIST

#define FIFOPATH1 "/home/xbq/dev/thread/fifo1"
#define FIFOPATH2 "/home/xbq/dev/thread/fifo2"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

using namespace std;

void* thread1 (void*)
{
int readfd, writefd;
char* buff = (char*)"nihao thread!";

writefd = open(FIFOPATH1, O_WRONLY, 0);
readfd = open(FIFOPATH2, O_RDONLY, 0);
int len = strlen(buff);

write(writefd, buff, len);
read(readfd, buff, 512);
cout << buff << "in thread1" << endl;
close(readfd);
close(writefd);
}

void* thread2 (void*)
{
int readfd, writefd, n;
char* buff;
buff = new char[15];

readfd = open(FIFOPATH1, O_RDONLY, 0);
writefd = open(FIFOPATH2, O_WRONLY, 0);

cout << read(readfd, buff, 13) << endl;
buff[strlen(buff)] = '\0';
cout << buff << "in thread2" << endl;
sprintf(buff, "%s%s", buff, "!!");
cout << buff << "in thread2" << endl;
write(writefd, buff, strlen(buff));

delete buff;
close(readfd);
close(writefd);
}

int main (void)
{
pthread_t tid1, tid2;
cout << pthread_self() << endl;
cout << mkfifo(FIFOPATH1, FILE_MODE);
cout << mkfifo(FIFOPATH2, FILE_MODE);

pthread_create(&tid1, NULL, thread1, NULL);
pthread_create(&tid2, NULL, thread2, NULL);

unlink(FIFOPATH1);
unlink(FIFOPATH2);
return 0;
}

#17


写一个线程一读,线程二写的简单例子试试。

#18


问题解决,结贴了!
由于本人的粗心大意,将源代码移动后忘记改变管道路径的宏定义:
#define FIFOPATH1 "/home/xbq/dev/thread/fifo1"
#define FIFOPATH2 "/home/xbq/dev/thread/fifo2"
由于我对Unix IO函数边界值不熟悉,所以程序中没有错误捕捉的代码,这也导致我没能及时发现这个低级错误!
踏踏实实,一步一个脚印地学习Unix编程!引以为戒

#19


引用 14 楼 billow_zhang 的回复:
read函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket描述字,管道文件等,这些文件的缺省read都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl设置取消文件O_NOBLOCK状态,也会产生阻塞的read效果。

详细~

#20


引用 14 楼 billow_zhang 的回复:
read函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket描述字,管道文件等,这些文件的缺省read都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl设置取消文件O_NOBLOCK状态,也会产生阻塞的read效果。


经典

#21


引用 20 楼 badboydw 的回复:
引用 14 楼 billow_zhang 的回复:
read函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket描述字,管道文件等,这些文件的缺省read都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl设置取消文件O_NOBLOCK状态,也会产生阻塞的read效果。


经典


确实经典,正在学习这块儿,今天把老帖子都翻出来了,看看,呵呵