Linux程序设计-1.文件I/O

1. 文件I/O

1.1 打开和可能创建一个文件open()

帮助文档:man 2 open
包含头文件:

  • #include <sys/types.h>
  • #include <sys/stat.h>
  • #include <fcntl.h>

函数原型:

  • int open(const char *pathname, int flags);
  • int open(const char *pathname, int flags, mode_t mode);
参数说明
pathname文件名
flags必选项:O_RDONLY|O_WRONLY|O_RDWR
可选项:O_APPEND|O_CREAT|O_EXCL|O_NONBLOCK|etc
mode创建文件时的权限
return成功:返回最小的可用文件描述符
失败:-1,并设置errno

注:Linux中一个进程最大文件描述符为1023;默认打开0:标准输入(STDIN_FIFENO);1:标准输出(STDOUT_FIFENO);2:标准错误(STDERR_FIFENO)
验证代码:

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

int main(int argc, char* argv[])
{
	int num = 3;
	char filename[128] = { 0 };
	while(1)
	{
		sprintf(filename, "temp_%04d.txt", num++);
		if(open(filename, O_RDONLY | O_CREAT, 0664) < 0)
		{
			perror("open error:");
			break;
		}
	}
	printf("num = %d", num - 1);
	return 0;
}

1.2 关闭一个文件描述符close()函数

帮助文档:man 2 close
包含头文件:

  • #include <unistd.h>

函数原型:

  • int close(int fd);
参数说明
fd文件描述符
return成功:0
失败:-1,并设置errno

代码示例:

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

int main(int argc, char* argv[])
{
	int fd = open(argv[1], O_RDONLY | O_CREAT, 0664);
	if(fd == -1)
		return -1;
	close(fd);
	return 0;
}

1.3 从一个文件描述符读取数据read()

帮助文档:man 2 read
包含头文件:

  • #include <unistd.h>

函数原型:

  • ssize_t read(int fd, void* buf, size_t count);
参数说明
fd文件描述符
buf缓冲区
count缓冲区大小
return成功:返回读到的字节大小
失败:-1,设置errno
0表示读到文件尾

1.4 写入数据到一个文件描述符write()

帮助文档:man 2 write
包含头文件:

  • #include <unistd.h>

函数原型:

  • ssize_t write(int fd, const void *buf, size_t count);
参数说明
fd文件描述符
buf缓冲区
count缓冲区大小
return成功:写入字节数
失败:-1,并设置errno
0:未写入

代码示例:

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

int main(int argc, char* argv[])
{
	int fd = open(argv[1], O_RDONLY);
	char buf[256] = { 0 };
	int ret = 0;
	while((ret = read(fd, buf, sizeof(buf))) > 0)
		write(STDOUT_FIFENO, buf, ret);
	close(fd);
	return 0;
}

1.5 重新定位读/写文件偏移量lseek()

帮助文档:man 2 lseek
包含头文件:

  • #include <sys/types.h>
  • #include <unistd.h>

函数原型:

  • off_t lseek(int fd, off_t offset, int whence);
参数说明
fd文件描述符
offset偏移量
whenceSEEK_SET:文件开始
SEEK_CUR:当前位置
SEEK_END:文件尾
return成功:当前位置到开始的字节数
失败:-1,设置errno

代码示例1:

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

int main(int argc, char* argv[])
{
	int fd = open(argv[1], O_RDONLY);
	int fileSize = lseek(fd, 0, SEEK_END);
	printf("%s size : %d\n", argv[1], fileSize);
	close(fd);
	return 0;
}

代码示例2:

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

int main(int argc, char* argv[])
{
	int fd = open(argv[1], O_RDWR | O_CREAT, 0664);
	int fileSize = lseek(fd, 1024, SEEK_END);
	write(fd, "write at least once", 19);
	close(fd);
	return 0;
}

1.6 阻塞与非阻塞

read()函数在读设备,读管道或读网络的时候,read()函数会阻塞
输入输出设备:/dev/tty
由于read()在非阻塞的情况下返回-1,所以当read()返回-1时需要判断errno的值

阻塞示例代码:

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

int main(int argc, char* argv[])
{
	int fd = open("/dev/tty", O_RDWR);
	char buf[256] = { 0 };
	int ret = 0;
	while(1)
	{
		printf("blocked\n");
		if(ret = read(fd, buf, sizeof(buf)));
			printf("\t%s\n", buf);
	}
	close(fd);
	return 0;
}

非阻塞示例代码:

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

int main(int argc, char* argv[])
{
	int fd = open("/dev/tty", O_RDWR|O_NONBLOCK);
	char buf[256] = { 0 };
	int ret = 0;
	while(1)
	{
		printf("nonblocking\n");
		if(ret = read(fd, buf, sizeof(buf)));
			printf("\t%s\n", buf);
		if(ret < 0)
		{
			perror("read error:"); # read error:Resource temporarily unavailable
			printf("ret=%d\n", ret); # ret = -1
		}
		sleep(1);
	}
	close(fd);
	return 0;
}

1.7 操作文件描述符fcntl()

帮助文档:man 2 fcntl
包含头文件:

  • #include <unistd.h>
  • #include <fcntl.h>

函数原型:
int fcntl(int fd, int cmd, ... / * arg */ );

参数说明
fd文件描述符
cmdF_GETFL|F_SETFD|etc

代码示例:

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

int main(int argc, char* argv[])
{
	int fd = open("/dev/tty", O_RDWR);
	
	// 通过fcntl()设置非阻塞
	int flags = fcntl(fd, F_GETFL);
	flags |= O_NONBLOCK;
	fcntl(fd, F_SETFL, flags);
	
	char buf[256] = { 0 };
	int ret = 0;
	while(1)
	{
		printf("nonblocking\n");
		if(ret = read(fd, buf, sizeof(buf)));
			printf("\t%s\n", buf);
		sleep(1);
	}
	close(fd);
	return 0;
}

1.8 复制文件描述符

1.8.1 dup()

帮助手册:man 2 dup
包含头文件:

  • `#include <unistd.h>

函数原型:
int dup(int oldfd);

参数说明
oldfd原文件描述符
return成功:新文件描述符
失败:-1,并设置errno

1.8.2 dup2()

帮助手册:man 2 dup2
包含头文件:

  • `#include <unistd.h>

函数原型:
int dup2(int oldfd, int newfd);

参数说明
oldfd原文件描述符
newfd新文件描述符
return成功:新文件描述符
失败:-1,并设置errno

主要用于重定向描述符
newfd指向oldfd

示例:

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

int main(int argc, char *argv[])
{
	int stdout_fifeno = dup(STDOUT_FILENO);
	int fd = open("test.txt", O_WRONLY | O_CREAT, 0664);
	dup2(fd, STDOUT_FILENO);
	printf("hello world\n");
	fflush(stdout);
	dup2(stdout_fifeno, STDOUT_FILENO);
	printf("Hello World\n");
	close(fd);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT灰猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值