Linux文件IO

Linux文件io

首先要知道文件描述表,通过这张表就可以找到对应的文件。从0开始编码到1023一共1024个。每个进程的前三个默认打开,也就是0,1,2分别指向标准输入、标准输出、标准错误三个文件,可以不用open直接使用。
pcb本质是结构体
一个进程有一个文件描述表:1024
前三个被占用
文件描述符的作用,通过他们找到对应的磁盘位置。

在这里插入图片描述
打开文件

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_CREAT
					创建文件是检测文件是否存在:O_EXCL
					如果文件存在,返回-1
					必须与O_CREAT一起使用
				追加文件:O_APPEND
				文件截断:O_TRUNC
				设置非阻塞:O_NONBLOCK
	model:
		只有创建新文件的时候才起作用

open函数的flags参数是一个32位整数,每一位对应不同的操作位

在这里插入图片描述

#include <unistd.h>

int close(int fd);//fd为open返回的文件描述符,这个时候文件描述符,就被关闭,不能找到文件位置
//close() returns zero on success.  On error, -1 is returned, and errno is set appropriately.
read 和write
 #include <unistd.h>
 ssize_t read(int fd, void *buf, size_t count);
参数:
	fd:open返回的值
	buf:缓冲区,存储要读取的数据
	count:缓冲区能存储的最大字节数sizeof(buf)
返回值:
	-1:失败
	成功:
		>0:读出的字节数
		=0:文件读完了
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
参数:
	fd:open的返回值文件描述符
	buf:要写到文件中的数据
	count:strlen(buf)
返回值:
	-1:失败
	>0:写到文件的字节数

程序示例:

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

int main(){
        //打开文件,
        int fd=open("./read.txt",O_RDWR);//以读写的方式打开文件read.txt文件
        printf("fd=%d\n",fd);
        if(fd==-1){
                perror("open error");  //打印失败信息
        }       
        //打开另一个文件,写操作
        int fd1=open("tmp",O_WRONLY|O_CREAT,0664);//以写的方式打开文件,如果没有创建新的文件,权限为0664
        printf("fd1=%d\n",fd1);
        
        //read

        char buf[4096];
        int len=read(fd,buf,sizeof(buf)); //从fd中读取4076个字节
        
        while(len>0){//这个意思是持续读,直到len=0说明读取的数据为0,也就是没有数据了
                //数据写到文件中
                int ret=write(fd1,buf,len);
                printf("ret=%d\n",ret);
                //read
                len=read(fd,buf,sizeof(buf));
        }
        close(fd);
        close(fd1);
        return 0;
}

在这里插入图片描述
每个进程都有一个文件描述符表,每个文件描述符指向一个文件表项,表项中有current file 和i-node的指针。
所以每一个进程都有一个lseek,比如第一个进程打开文件的时候,是文件指针偏移为0,另一个进程文件指针偏移量也为0,各自维护自己的。

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
//如果whence SEEK_SET参数offset=0 那么返回值为0
//					    offset=10那么返回值为10
//说白了就是相对文件指针的偏移量
a.文件指针移动到头部
lseek(fd,0,SEEK_SET);
b.获取指针当前位置:
	int  len=lseek(fd,0,SEEK_CUR);
c获取文件长度:
	int len=lseek(fd,0,SEEK_END);
文件拓展
文件原大小100K,拓展为1100k
	lseek(fd,1000,SEEK_END);//这时候不会拓展成功
	最后做一次写操作
	write(fd,"a",1);

在这里插入图片描述
这里不是乱码而是‘\0’起到占位的作用。

errno和perror

errno是一个全局变量,不同的值,对应不同的错误信息。
perror是一个函数,把errno对应的信息打印出来。

 #include <stdio.h>
 void perror(const char *s);

perror("发生错误")
//显示信息为:发生错误:error info
阻塞和非阻塞

阻塞和非阻塞是文件的属性,并不是程序的属性
普通文件默认非阻塞
终端设备默认阻塞,管道、套接字默认阻塞

如果一个程序app,冲终端读取10字符,而为人输入15个字符会发生什么现象?

bash默认是前台程序
./app 启动了一个程序,前台程序这个时候变成了app,而bash变成了后台程序。
./app等待用户输入10个字符,而实际输入了15个字符,剩下的还在输入终端缓冲区中。
read函数解除阻塞读取缓冲区数据,write,程序结束。
bash从后台程序变为前台程序,检测到了缓冲区数据,将缓冲区作为shell命令区做了解析。

获取文件属性
struct stat {
               dev_t     st_dev;         /* ID of device containing file */
               ino_t     st_ino;         /* inode number */
               mode_t    st_mode;        /* protection */***********常用***********
               nlink_t   st_nlink;       /* number of hard links */
               uid_t     st_uid;         /* user ID of owner */*****常用***********
               gid_t     st_gid;         /* group ID of owner */****常用***********
               dev_t     st_rdev;        /* device ID (if special file) */
               off_t     st_size;        /* total size, in bytes */*常用***********
               blksize_t st_blksize;     /* blocksize for filesystem I/O */
               blkcnt_t  st_blocks;      /* number of 512B blocks allocated */

               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */

               struct timespec st_atim;  /* time of last access */
               struct timespec st_mtim;  /* time of last modification */***常用*****
               struct timespec st_ctim;  /* time of last status change */

           #define st_atime st_atim.tv_sec      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

在这里插入图片描述

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

int stat(const char *pathname, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
//lstat 读取的是连接文件
//stat读取的是连接文件指向的文件属性
	

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 #include <unistd.h>

 int dup(int oldfd);
 //将oldfd的文件描述符所指的内容复制给新的文件描述符,返回从3到1023最小的且没有被占用的
 int dup2(int oldfd, int newfd);
//如果newfd已经指向了一个文件先close(newfd)然后执行oldfd只向的文件。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值