linux服务器开发学习笔记02

第四讲 文件IO

用户空间的大量缓存
在这里插入图片描述
指针File结构体

0 标准输入
1 标准输出
2 标准出错

man open
在这里插入图片描述
必须要加入的头文件
SYNOPSIS
在这里插入图片描述

open c语言没有函数重载的内容却这样

在这里插入图片描述
… 可变参数
open 文件描述符
open打开一个或者创建一个文件
flags 打开的方式 多种打开方式的总和的话需要用位或
在这里插入图片描述
在这里插入图片描述
创建文件的话要加多一个权限
在这里插入图片描述
2>&1
对于2>&1的理解,2就是标准错误,1是标准输出,那么这条命令不就是相当于把标准错误重定向到标准输出么?

是的。为什么是&1而不是1,这里& 符号是什么?& 符号可以理解为引用(reference)。&1 就是对标准输出的引用。「我觉得可以理解为我们C语言里面的取地址符号,拿到标准输出的地址,往地址里面灌什么,标准输出就会给你输出什么」

nohup
nohup 指的是把命令放后台运行,并且不挂断的运行,他会把输出默认定向到文件nohup.out中

&
这个指令指的是在后台运行

4.2open函数的用法

在这里插入图片描述
fprintf发送格式化输出到流stream中
在这里插入图片描述
stderr是FileStream
标准输出将正常数据输出到标准输出文件
将错误信息送到标准错误文件

argc(参数个数) argv(参数的字符串数组的指针)
在这里插入图片描述
EXIT_FAILURE 可以作为exit ()的参数来使用,表示没有成功地执行一个程序

open(argv[1],O_RDONLY)
以只读的情况打开文件
open函数返回的错误信息
在这里插入图片描述
成功了返回文件描述符,错误了返回-1

错误类型
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
出错了的情况
open返回-1,打印错误信息
打印文件名,行数,错误号对应的信息
在这里插入图片描述

fprintf(stderr,"[%s][%d]:%s\n",__FILE__,__LINE__,strerror(errno))

打印错误信息strerror(errno)

如果没有出错就打印文件描述符
在这里插入图片描述

总的处理

open函数_>fcntl.h
errno
strerror string.h头文件
在这里插入图片描述

编译一下 gcc
在这里插入图片描述
在这里插入图片描述
打开一个文件
012文件描述符已经被系统占用了
0 标准输入
1标准输出
2标准错误

文件描述符是用来操作文件的一个标识,是一个数字。 ps -ef 可见所有进程,选择一个进程的 PID,如 22575
查看该进程所有的文件描述符:lsof -p 进程号

可见,没有对它们重定向的话,默认是指向 当前终端。在这里插入图片描述

在这里插入图片描述

4.3read函数的用法

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


#define E_EXIT(msg)\
do{\
fprintf(stderr,"[%s][%d]:%s:%s\n",__FILE__,__LINE__,msg,strerror(errno));\
	exit(EXIT_FAILURE);\
}while(0)





fprintf()
char buf[BUF_SIZE];
int r = read(fd,buf,BUF_SIZE);

while(1){
//每一次读取之前应该将这块区域的内容清空
memset(buf,0x00,sizeof(buf));
//memset在一段内存中填充某个给定的值
int r=read(fd,buf,BUF_SIZE)if(r==0){
	break;
	}
//r==0的时候就是读完的时候
printf("%s",buf)if(r==-1){
/*	fprintf(stderr,"[%s][%d]:%s\n",__FILE__,__LINE__,strerror(errno));
	exit(EXIT_FAILURE);
	*/
	//异常退出
	E_EXIT("read");
	}
}

在这里插入图片描述
配置自己电脑的vim,配置一个根据个人习惯使用的.vimrc文件。我的有以下功能等,读者可以根据自己的

个人喜好去配置自己的vim。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.4拷贝函数的write和close函数用法

man 2 write
在这里插入图片描述

write读取源文件内容,拷贝到目标文件

vim的分屏功能
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
argv[0]可执行文件
argv[1]源文件
argv[2]目标文件

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

}
在这里插入图片描述

在这里插入图片描述
循环读取文件
在这里插入图片描述
在这里插入图片描述
记得memset
在这里插入图片描述
在这里插入图片描述
没有文件就要创建文件,open的参数里面要加上O_CREATE
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

umask
文件权限
原来的umask=0022 =》000 010 010 按位取反
和给出的数 110 110 110 进行按位与
110 110 110 &~000 010 010
=110 100 100
受umask的影响

gcc -o
在这里插入图片描述

在这里插入图片描述
vimdiff 查看两个文件是否相同
vimdiff open.c open.bk
按空格键将文件的内容全部显示出来
在这里插入图片描述

4.5 open其他选项用法

O_TRUNC
截断,如果一个文件已经存在
再往里面写内容将原来文件清空然后再写

正常情况下
如果文件有内容从前面覆盖
在这里插入图片描述

在这里插入图片描述
需要清空的话就将open函数与上一个O_TRUNC
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

man ftruncate

在这里插入图片描述
truncate清空内容
写日志
追加 O_APPEND
在这里插入图片描述
在这里插入图片描述
后面要讲的
在这里插入图片描述
O_EXCL 必须和creat选项(O_CREAT)一起,否则没有意义
当要创建的文件是存在的那么就会报错
在这里插入图片描述
在这里插入图片描述
如果没有处理报错是不会显示的
在这里插入图片描述
必须加上if(fd==-1)之后的操作

./a.out表示当前目录下的a.out文件。

a.out 是linux/unix环境下gcc编译源代码(c/c++)并连接产生的默认执行文件名。./a.out表示当前目录下的a.out文件。一个单独的点号指代当前文件路径。因为linux/unix搜索可执行文件的默认路径需要指定,没有./两个符号指定路径的话,新编译的文件操作系统找不到。

在这里插入图片描述

4.6lseek函数的用法

读写文件一般是按顺序读写的
lseek
随机读取
表示当前读到那个位置
man lseek
在这里插入图片描述
在这里插入图片描述
unistd.h头文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

close(fd)记得关闭打开的文件
write

这里不涉及内存字节的补齐的所以
34字节

这里
在这里插入图片描述
可以直接跳到stu.c的33行来修改内容

ls -l 查看文件的大小
在这里插入图片描述
dat 文件
把结构体数组整块搬过去的

想要读取dat 文件在这里插入图片描述
dat 文件并不显示asc码的值

1.首先复制一份 stu.c的内容带read.c 删掉主函数的内容
2.主函数打开 stu.dat O_RDONLY
3.然后需要判断一下open返回的打开有没有出错
4.然后输出需要查询的第几个学生信息
5.lseek定位哪个学生
5.返回信息
写1不偏移
写2偏移一个

int num;
printf("%d",num);
scanf("%d",&num);
lseek(fd,(num-1)*sizeof(stu_t),SEEK_SET);
//定位到指定的结构体数组的位置
stu_t st;
//定义新的结构体数组
read(fd,&st,sizeof(stu_t));
//将数据读到指定的位置
printf("id=%d,name=%s\n",st.id,st.name);

如何求一个文件的大小
偏移到文件的结尾

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>

int main(int argc,char *argv[]){
int fd=open(argv[1],O_RDWR);

int r=lseek(fd,0,SEEK_END);
printf("file size = %d\n",r);
close(fd);
}

在这里插入图片描述

gcc编译一下

在这里插入图片描述

lseek的返回值就是新偏移的位置

./a.out copy.c 测试一下别的文件
在这里插入图片描述
在这里插入图片描述

ls -l test 查看test文件的详情
在这里插入图片描述
在这里插入图片描述

cat 只能显示能显示的
od 查看文件内容命令
od -c test 可以看到不可显示的
在这里插入图片描述
空洞文件
在这里插入图片描述
-lh以不同格式显示

od -c 查看文件的内容
在这里插入图片描述
du 看占用磁盘空间
在这里插入图片描述
在这里插入图片描述

4.8 竟态条件和文件描述符

追加

在open的时候加上append

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

文件描述符总是和文件一一对应的

一个进程能打开多少个文件是受限制的
在这里插入图片描述
open files 1024
可以修改的

在这里插入图片描述
在这里插入图片描述
文件描述符表示close exct

文件偏移量会变的
状态标志read write
对应磁盘 i-node表系统级
ls -i 每一个文件对应一个索引号,找到在磁盘哪个位置

在这里插入图片描述
输出重定向
在这里插入图片描述


文件描述符的复制
在这里插入图片描述
dup
在这里插入图片描述
在这里插入图片描述
输出重定向就是用了文件描述符复制这个功能
dup从小到大选择第一个没有被用到的文件描述符
dup2(oldfd,newfd)
在这里插入图片描述
dup2做的事和dup做的事是一样的

清空文件内容 > hehe
在这里插入图片描述

还有一个函数可以用 fctnl()
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
同时只能有一个一个


文件的锁
man fcntl
在这里插入图片描述
w等待
无 w报错
类型
在这里插入图片描述
范围

在这里插入图片描述
start开始的位置
在这里插入图片描述len start都是0 表示锁全文

在这里插入图片描述
在这里插入图片描述
lock.l_type=F_UNLCK

gcc lock.c
在这里插入图片描述
阻塞了
在这里插入图片描述
在这里插入图片描述
打开文件的时候告诉内核应该怎样设置 状态标志
还有就是 程序执行过程中通过fcntl标志设置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
缺省的就是阻塞的

在这里插入图片描述

4.11 文件系统

在这里插入图片描述
i节点表
数据是什么
在这里插入图片描述
数据指针
数据指针的指针


stat
获取文件的元数据信息
在这里插入图片描述
如何获取文件的信息
stat
man stat
在这里插入图片描述
在这里插入图片描述

st_nlink
硬链接数
uid 拥有者的id
gid 拥有者的组id
在这里插入图片描述

4.12文件类型和文件权限的获取

在这里插入图片描述

stat
在文件sys/stat.h头文件有

struct stat buf;
if(stat(argv[1],&buf)==-1){
//将信息装到struct 结构体中
perror(“stat”);
exit(EXIT_FAILURE);
//错误退出
}

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

在这里插入图片描述
在这里插入图片描述
上面
这么写是错的,下面这样写才是对的

在这里插入图片描述

我们,用户,本组,其他

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

ls -l命令的实现

stat 有 nlink 成员
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
getpwuid获得7列信息
在这里插入图片描述

需要用到 <pwd.h> 的头文件

在这里插入图片描述
如何根据组id获得组名
在这里插入图片描述
getgrgid
在这里插入图片描述
包含头文件 grp.h
在这里插入图片描述
getgrgid(buf.st_gid);
然后再用得到的对象->gr_name
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
获取系统的时间time()
转换成时间

在这里插入图片描述
man localtime
在这里插入图片描述
在这里插入图片描述
需要include<time.h>
在这里插入图片描述
在这里插入图片描述
获取时间
在这里插入图片描述

思考:如果文件是软连接呢?

4.14目录

在这里插入图片描述
操作目录的函数
在这里插入图片描述
man 3 opendir
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
循环读取文件
d_name
隐藏文件就是第一个文件是.
在这里插入图片描述

DIR *pd=opendir(".");
if(pd==NULL)
perror("opendir"),exit(1);

//z直接打印错误perror
struct dirent *dir=NULL;
while((pdir=readdir(pd))!=NULL){
if(pdir->d.name[0]=='.')
continue;
printf("%s\t",pdir->d_name);
}
printf("\n");
closedir(pd);

4.15 用链表显示目录内容

创建一个链表
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

文件项目

日志文件
等级
配置文件
#开始 说明
network -> ip port
log -> log_name log_level
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
找最优子问题
在这里插入图片描述
在这里插入图片描述
做几个假设
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
转移方程
在这里插入图片描述
在这里插入图片描述
什么时候定义初始条件
在这里插入图片描述
边界条件数组不能越界
在这里插入图片描述
从上到下

在这里插入图片描述
在这里插入图片描述
动态规划组成部分四:计算顺序
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值