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;

}

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


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

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

   

    (等待5秒后输出)

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


    0x01

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

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>


#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;

}
    控制台将输出:

    
    当没有数据可读时:

    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 <sys/stat.h>
#include <unistd.h>
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、付费专栏及课程。

余额充值