linux进程文件描述符与管道,Linux系统编程-管道与文件

0x00

管道经常用于进程间通信,进程间通过管道的读端和写端进程通信。

我们介绍一个比较简单的例子。

int main(int argc, char *argv[])

{

int pipefd[2];

if (pipe(pipefd) == -1)

ERR_EXIT("pipe error");

pid_t pid;

pid = fork();

if (pid == -1)

ERR_EXIT("fork error");

if (pid == 0) //子进程

{

sleep(5);

close(pipefd[0]); //关闭读端

write(pipefd[1], "hello", 5); //写端

close(pipefd[1]);

exit(EXIT_SUCCESS);

}

close(pipefd[1]); //父进程,关闭写端

char buf[10] = {0};

read(pipefd[0], buf, 10); //读端

printf("buf=%s\n", buf);

return 0;

}

我们来看一张图来理解这个程序。

0818b9ca8b590ca3270a3433284dd417.png

父进程和子进程间拥有各自的文件描述符,但是他们共同操作着同一个管道,所以可以实现进程间通信。

在终端控制台的运行结果:

0818b9ca8b590ca3270a3433284dd417.png

(等待5秒后输出)

注意read函数,是阻塞读取管道中的内容。

0x01

如果想不阻塞读取管道的内容,可以使用fcntl来改变文件属性,使文件描述符处于阻塞模式:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

int main(int argc, char *argv[])

{

int pipefd[2];

if (pipe(pipefd) == -1)

ERR_EXIT("pipe error");

pid_t pid;

pid = fork();

if (pid == -1)

ERR_EXIT("fork error");

if (pid == 0)

{

sleep(3);

close(pipefd[0]);

write(pipefd[1], "hello", 5);

close(pipefd[1]);

exit(EXIT_SUCCESS);

}

close(pipefd[1]);

char buf[10] = {0};

int flags = fcntl(pipefd[0], F_GETFL);

fcntl(pipefd[0], F_SETFL, flags | O_NONBLOCK);

int ret = read(pipefd[0], buf, 10);

if (ret == -1)

ERR_EXIT("read error");

printf("buf=%s\n", buf);

return 0;

}    控制台将输出:

0818b9ca8b590ca3270a3433284dd417.png

当没有数据可读时:

O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。

O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。

0x02

下午谈一下文件。列举出文件的基本操作:

1、int open(const char *pathname, int flags);  打开文件,返回文件描述符。

2、ssize_t read(int fd, void *buf, size_t count); 从文件的当前偏移读取count个字节到buf缓冲区。

3、ssize_t write(int fd, const void *buf, size_t count); 向文件的当前偏移写入count个字节,这些字节来源于buf。

4、off_t lseek(int fd, off_t offset, int whence); 用来移动文件流的读写位置。

参数 whence 为下列其中一种:

SEEK_SET 从距文件开头offset 位移量为新的读写位置。

SEEK_CUR 以目前的读写位置往后增加offset 个位移量。

SEEK_END 将读写位置指向文件尾后再增加offset 个位移量. 当whence 值为SEEK_CUR 或 SEEK_END 时, 参数offset 允许负值的出现。

5、int fcntl(int fd, int cmd, ... /* arg */ ); 用来改变文件的属性。

int flags = fcntl(pipefd[0], F_GETFL);

fcntl(pipefd[0], F_SETFL, flags | O_NONBLOCK);    6、int stat(const char * file_name, struct stat *buf); 用来获取文件状态 。

#include

#include

main()

{

struct stat buf;

stat("/etc/passwd", &buf);

printf("/etc/passwd file size = %d \n", buf.st_size);

}    参考

http://c.biancheng.net/cpp/html/326.html。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值