前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >文件I/O

文件I/O

作者头像
看、未来
发布2020-08-26 10:29:24
7350
发布2020-08-26 10:29:24
举报
文章被收录于专栏:CSDN搜“看,未来”

1.1 C标准函数与系统函数的区别

有一定编程基础的小伙伴应该都接触过文件编程吧,file. 在C语言里面是包一个<file.h>的头

每一个文件都有一个缓冲区,C和系统函数的区别也不想说太多,系统函数可以实现不同进程共享一个缓冲区,而C函数不行。

1.2 PCB的概念

PCB(process control block),进程控制块。 Linux的进程控制块为一个由结构task_struct所定义的数据结构,task_struct存/include/ linux/sched.h 中,其中包括管理进程所需的各种信息。 在创建一个新进程时,系统在内存中申请一个空的task_struct区,即空闲PCB块,并填入所需信息。

1.3 open/close

首先了解一下文件描述符,和文件描述符表。 注意:以下内容记住基于进程,所以文件描述符和符表都存在PCB里面了。 文件描述符表:纪录文件描述符使用情况的表。 文件标书符:在一个进程创建时吗,默认自动打开三个文件,即生成了三个文件描述符: STDINFILENO —>0 STDOUT_FILENO —>1 STDERR_FILENO —>2 标准输入输出流和标准错误流

之后再开辟新文件就会生成新的文件描述符,默认使用空闲的最小的文件描述符。 这里就可以将输入输出重定向:关闭输入输出流,而后重新打开文件,就可以将输入输出重定向到新开文件中。

好,我们来看怎么打开文件z

代码语言:javascript
复制
#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);

//一般用fd接收返回值

//返回值 :成功返回重新分配的文件描述符,出错则返回-1并设置errno

参数释义: pathname:要打开或创建的文件名,既可以是绝对目录,也可以是相对目录。 flags:打开模式: O_RDONLY 以只读形式打开 O_WRONLY 以只写形式打开 O_RDWR 可读可写形式打开 O_APPEND 表示追加,从文件末尾添加内容,而不覆盖原有内容 O_CREAT 若文件不存在则创建,仅此处会用到第三个参数,赋予文件权限 O_EXCL 和 O_CREAT 共用,如果文件已存在则出错返回 O_TRUNC 这个咱也没用过,如果文件已存在,并且有可写模式打开,则将其长度截断为0字节 O_NONBLOCK 对于设备文件,做非阻塞I/O.

第三个参数指定权限,以八进制数表示。

再看一下如何关闭文件

代码语言:javascript
复制
#include <unistd.h>

int close(int fd);

//返回值:成功返回0,失败返回-1并设置errno

参数释义: fd为要关闭的文件描述符。 在进程结束时,系统自动调用close关闭所有文件。

1.4 read/write

read函数从打开的文件中读取数据 write函数向打开的文件中写入数据

代码语言:javascript
复制
#include <unistd.h>

ssize_t read(int fd,void *buf,size_t count);
ssize_t write(int fd,void *buf,size_t count);

//返回值:成功返回读取/写入的字节数,失败返回-1并设置errno。

参数释义: fd:文件描述符 buf:缓存,一般用char数组 count:要读取/写入的字节数

ssize_t:表示有符号的size_t。

有些情况下,count可能不会那么刚好。 从终端设读,通常以行为单位,读到换行符就返回了 从网络读后面socket部分会再说

1.5 阻塞和非阻塞

读常规文件是不会阻塞的 从终端设备或网络读取就不一定了 如果终端输入的数据没有换行符,调用read的终端设备就会阻塞 如果网络上没有收到数据包,调用read从网络读就会阻塞 至于阻塞多久那就不确定了 如果一直没有数据到就一直阻塞在那里

解决阻塞的一个办法叫轮询

1.6 lseek

每个打开的文件都会纪录当前读写的位置,不过那个O_APPEND比较特殊点。 也可以通过lseek来人为操控文件指针偏移位置。

上代码:

代码语言:javascript
复制
#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd,off_t offset,int whence);

//这里允许偏移超过文件末尾,中间空出来的位置都是0.

参数释义:fd文件描述符 offset:偏移量 whence:偏移的起始位置

whence: SEEK_SET:从文件开始处计算 SEEK_CUR:从当前文件偏移处计算 SEEK_END:从文件结束处计算

若lseek成功执行,返回一个新的偏移量。

注意:偏移之后写入一个空值,不然会偏移不成功。

1.7 fcntl

可以用fcntl对一个已打开的文件进行修改属性,而不必重新open一个文件 不过这个我是没试过了

不过文件锁需要用到这个

Linux中文件记录锁可以对文件某一区域进行文件记录锁的控制。它是通过fcntl函数来实现的。

代码语言:javascript
复制
#include <unistd.h>
#include <fcntl.h>

int fcntl (int fd,int cmd,struct flck *lock);
//功能说明:管理文件记录锁的操作
//返回值:调用成功返回0,失败返回-1

参数释义: fd:文件描述符; cmd:功能符号; (F_SETLK用来设置或释放锁; F_GETLK用来获得锁信息;) lock:存储锁信息的结构体指针;

struct flock { short l_type; /* 锁的类型 / short l_whence; / 偏移量的起始位置: / off_t l_start; / 从l_whence的偏移量 / off_t l_len; / 从l_start开始的字节数 / pid_t l_pid; / 锁所属进程ID(一般不用) */ } l_type有F_RDLCK读锁、F_WRLCK写锁及F_UNLCK空锁。 l_whence有SEEK_SET、SEEK_CUR和SEEK_END。 l_len为0时表示从起点开始直至最大可能位置为止。

因为这个我也不太会,但是我想会,那就上代码

代码语言:javascript
复制
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(){
	int fd;
	struct flock lock; //声明锁变量
	
	if((fd = open("example",O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1)
	{
		printf("open file error\n");
		return -1;
	}
	
	memset(&lock,0,sizeof(struct flock));//清空锁变量

	//设置锁变量
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	
	//拿到锁则对文件执行后续操作
	if(fcntl(fd,F_GETLK,&lock) == 0)
	{
		//判断该锁是否空锁
		if(lock.l_type != F_UNLCK)
		{
			printf("lock can not by set in fd\n");
		}
		else
		{
			lock.l_type = F_WRLCK;//要上锁时才给出锁的类型
			if(fcntl(fd,F_SETLK,&lock) == 0)
				printf("set write lock success!\n");
			else
				printf("set write lock fail!\n");
			getchar();
			lock.l_type = F_UNLCK;//在释放锁之前将锁置空
			fcntl(fd,F_SETLK,&lock);//释放锁
		}
	}
	close(fd);//关闭文件描述符
	return 0;
}
1.8 ioctl

ioctl用于向设备发送控制和配置命令,有些命令也需要读写一些数据,但是这些数据是不能用write/read来进行读写的,如串口线啊之类的。

代码语言:javascript
复制
#include <sys/ioctl.h>

int ioctl(int d,int request,······);

//d是某个设备的文件描述符,request 是ioctl的命令。可变参数取决于request。
//成功返回一个值,也是取决于request,失败返回-1并设置而errno。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/01/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 C标准函数与系统函数的区别
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档