05-Linux系统编程-第02天(文件系统、目录操作、dup2)
1 课程回顾
02-文件存储
文件名不在inode里 而是保存在一个叫dentry的结构体里了
格式化就是指定一组规则
指定对文件的存储及读取的一般方法
linux下主要使用 ext2 ext3 ext4
ext2 是类unix系统的基础文件系统类型
高版本要向低版本兼容
03-ext2文件系统
拿网吧示例 :
有个人上机了 那么老板的管理系统上旧标注这个人上机了
(把这个管理系统的电脑也放到这12个机器中把…
data blocks 存的数据
inode table 存的inode结构体
inode bitmap 描述inodetable里每个inode使用情况
(老板的机器就像是bitmap 来查看inode使用情况)
block bitmap 描述block的使用情况(描述的是整个块组的所有的block,包括它自己)
super block 描述整个分区的文件系统信息
GDT 块组描述符表
04-ext2文件系统2
一个groupblock是由无数多个相同大小的数据块组成的
格式化的时候就生成很多inode都指定好了
Touch一个文件就是从inode中拿一个分给你
(先有inode 后有文件
Inode位图就是来说明你这个inode是否被划分出去了 如果被划分出去了 某个inode bitmap上就划个1… …
疑惑:
文件存储之前也不知道磁盘会存多少个文件 那么应该划分多少个inode?
操作系统的操作机理是按照8Kb对应一个inode
从整个块组中除去前面的内容后剩下的(直接用数据块大小近似)除以8 得到多少个就在inode里分配多少个
但是有的文件1kb都不到 有文件上g 会出现inode多余浪费或inode不够的情况..
所以大家使用的电脑的磁盘都不能百分之百完全利用 都有一定的浪费
如果能预见到磁盘存放的数据 比如寸电影,就可以把inode调大一点
如果存小文件就可以把inode放小
每8KB划分一个inode的机制是系统决定的
一个inode结构体128byte
vi hello.c 存放到磁盘上比如说占用了一个block 1kb
inode结构体存着这个文件的编号 然后去磁盘找对应编号的文件
数据块寻址:
inode里面会有一个索引项
来负责找数据块
如果一个文件有多个数据块 这些数据块很可能不是连续存放的。 这些数据块通过inode中的索引项block来找到
这样的索引项一共有15个,Block[0]-Block[14] 每个索引项占4字节 前12个索引项都表示块的编号 如果block[0]保存27 表示第27个块是该文件的数据库快
如果创建的文件系统指定的块大小是1kb 这种方法可以表示从0~12kb的文件 如果剩下三个索引项也这么用 那么旧只能表示最大15kb的文件了 这是远远不够的
剩下3个索引项block[12] block[13] block[14] 是间接索引 假设块大小为b 那么一个间接寻址块中可以存放b/4个索引项 指向b/4个数据块。
如: block = 1kb, 那么 block[0] –block[12] 都用上 最大可以表示 12 + 1024/4 = 268K大小的文件 虽然大很多 但仍然不够用。
于是有了二级间接寻址块Block[13] 三级间接寻址块Block[14] 这样1K的块 最大可以表示16.06GB大小的文件。
(12 13 14间接索引 分别是一级索引 二级索引 三级索引)
拿12举例 假设block是1kb 那么 12指向的块分成1k/4 256小块 每个小块自身大小是4byte 这个小块指向一个1kb的block数据块
如果是二级索引 上面的256个小块中每个小块再指向一个1k/4的块..
…
结论: superblock划分1k, 1个inode最大索引16.06GB文件
目前使用的linux操作系统一般划分block是4k 所以一个inode最大索引64gb大小文件
疑问: 一个分区里要划分多少个块组?
答: 使用块位图描述整个分区所有块的使用情况
如果superblock指定一个逻辑块是1k 那么,因为块位图要占一个块 所以块位图也是1k
1k 大小是1024*8个位 此时一个块组最多可以有1024*8个块
如果整个分区有s个块 那么就会有s/1024*8 个块组
。。。
05-stat函数
man 2 stat
注意:
blocksize 就是superblock中指定的一个逻辑block的大小
用一下shell command stat 查看一下文件状态:
IO块:操作系统的逻辑I/O块设定的大小 (默认咱们用的是4kb
( )
块: 使用扇区的个数 512*24
设备:组设备号和设备号
Inode: Inode编号
读取一下makefile文件的大小
和ll结果一样都是208
st_mode 权限:
st_mode本质也是位图
后三位用来描述other 的 r w x权限…
user… other… group…
最前面的四位描述文件类型
4个位有2^4种情况 可以描述16种文件类型
但是linux实际就7种
在未来的20,30年如果有新加入的文件类型 就留有余地了
0001 普通文件
0010 目录
… …
这里就不做位与 位或操作了 操作系统提供了宏函数:
参数就是st_mode
06-穿透符号链接
ln –s stat stat.s
软连接显示的不对
对于stat来说,它是会穿透符号链接的系统调用
stat会穿透链接并找到源文件
使用lstate不会穿透链接
把stat函数修改成lstate,然后再跑一遍:
扩展:
man 2 stat
然后看example:
page中的例子:
他的判断方法使用switch case 使用st_mode与宏位与 最后用宏来判断:
掩码S_IFMT
f 就是4个1
还有一些别的掩码
07-特殊权限位
最后一个t表示黏住位
chmod 01777 在前面加一个1 设置黏住位
ll 就显示黏住位了 最后一个t表示黏住位
比如中国银行有一个改密码的业务需求,
普通用户不能取修改数据库内的数据 修改密码
要给用户授权变成超级用户取改?
或者用户提交改密码的请求到中国银行,由root用户去改
setSIT = 1 ,用户的有效用户ID就发生变化了
接下来A用户,B用户,C用户 直接调用程序修改密码就行了
setuid 设置用户id位
setgid 设置用户组id位
ll a.out
这就是一个可执行文件 所有者是itcast
./a.out就开始执行这个程序了
进程在运行期间 所有者就是itcast 这个就是实际用户ID(UID
默认情况下EID和UID相同,
但是,当文件setID被设置后两个ID则有可能不一样,
当执行一个文件加sudo的时候 当前执行期间有效用户变成root用户 但是实际用户并没有改变
特殊权限位的三位
设置组id位
设置用户id位
黏住位
08-文件操作常用函数
access:
测试是否有读权限 写权限 和执行权限
0 返回 说明成功
chmod:
access.c:
truncate不仅能清空,也可以将文件设置成指定长度
(都不需要open或者close 直接就能运行
目的是为了文件共享
也就是硬链接
Inode号一样 但是文件名一样
上面这个东西就叫dentry
或者叫 directory entry 目录项
link函数 为一个已经存在的文件创建目录项(也就是创建硬链接)
以上其实就是实现了一个ln命令
unlink:
man 2 unlink:
ulink作用 删除一个文件的dentry
09-隐式回收和其他文件操作函数
查看上面代码:
创建文件 然后像文件里写入内容,中间输出”Enter a key to continue” 然后getchar()等待用户输入, 最后unlink
make
然后在getchar没输入的时候重新开一个终端cat temp.txt
能查看到,
如果此时我按了一个键 再cat 就发现temp已经被删除掉了
注意: 如果再printf前面加上一个p[0] = ‘H‘
会引起段错误, 此时查看temp发现临时文件仍然存在
(因为没有走到unlink就结束了)
如果希望实现: getchar()之前文件存在,getchar之后文件删除的效果,要怎么做?
解决方法是写错误处理,如果出错的时候把文件删除
注意:段错误是运行时错误 不能捕捉, 是不可逆的。
需要用*(后面讲到 信号) 才能捕捉
文件open完了紧接着就调用unlink 。。 看看能删了不
看一下代码
make 然后运行一下,
make 运行,ls查看文件不存在了
既然删除成功,为什么还能write, write成功了…write没有报错.. 是怎么回事呢
把p[0]=’H’ 打开 再试一下:
按理说只要改p[0]就会报段错误
运行一下,的确报段错误了, temp.txt也不存在了,
… … emmmm这不废话么 但是还是
有一个不理解的地方: 文件都已经给删除掉了,为什么write函数没有报错
当unlink文件的时候 只是删除了一个dentry(directory entry) 没有线连像inode了
删除的时候 会把dentry给删除掉 没有dentry指向inode了
但是磁盘上的数据没有擦除掉
inodemap上的某个位置从1变成0了 但是磁盘盘块上的数据还是存在的
将来再有数据来了 这个盘块会分配给新的数据 新的数据会直接将原有的数据给覆盖掉
磁盘使用就是新数据覆盖旧数据
所以格式化并不安全 格式化只是把左边两条线断开了..
磁盘上的数据并没有抹掉
把这些箭头重新生成的过程 叫 数据恢复
ulink只是让文件具备了被删除的基础,至于什么时候被删除掉由系统说了算 程序不管
操作系统如果有需求可以把这段空间拿给其他进程用 我不用了
至于什么时候释放掉,系统说了算 ,程序不管了。
刚才的程序为什么unlink后还能write,因为unlink后只是把dentry删除掉了 ,从用户的层面ls –l 已经看不到这个文件了 但是磁盘上的文件没有被真正删除
所以还能write 因为系统调用write 内核结构文件结构体去访问的 不需要再借助路径了,到内核里就借助结构体指针了
打开unlink的进程没有关闭 内核没有执行清空 进程如果结束 就不能真正的write了
(所以write没有报错)
还有一个问题, open了一个文件以后 中间出现段错误 代码就不再向下执行了,
后面没有执行到close 所以之前open的文件一直是打开的状态
假如说打开的文件占用文件描述符是3 (0,1,2分别是标准输入。标准输出。标准出错) 下次我再执行a.out,再打开就占4了 如果执行1024遍就耗光了?
隐式回收:
当进程结束运行时 所有该进程打开的文件都会被关闭,申请的内存空间会被释放,系统的这一特性称为隐式回收系统资源。
思考一下。。执行./a.out的时候 0 1 2 就自动打开了 但是从来不用写close(0) close(1) close(2)
这个就是依赖的隐式回收
malloc申请内存 如果进程不结束的话,申请的内存会越积越多 但是如果进程关闭后其实就被操作系统隐式回收了
link是建立dentry
symlink是软链接(符号链接
思考如何实现ln命令:
ln 硬链接
ln –s 软连接
如果argv[1]是-s就去调用symlink
readlink 是不穿透的
ls –l是不穿透的
(左侧l 指示这是一个硬链接)
假设test.soft是指向test目录的一个软连接
cd test.soft才是穿透
readlink test.soft 是不穿透的
(注意这里是shell里的readlink命令) (man 1 readlink)
下面说的是readlink函数: (man 2 readlink)
rename函数:
10-目录操作函数1
./ 表示当前进程工作目录
当前进程就是 shell进程
../ 表示shell进程当前工作目录的上一级目录
pwd 打印的是shell进程的工作目录(man 1 pwd)
./a.out里getcwd 打印的是a.out进程执行的工作目录
(在第三卷了 是一个标准库函数)
test.c:
结果:
打印输出的目录变了
为什么执行完后出来的而目录没变?
答案:出来以后的目录是shell进程的目录 不是a.out进程的目录
怎么让shell调用chdir呢.. 其实在shell里执行 .. 就是向上一级走了
改变一下test.c:
结果:
注意如果目录没有执行权限了就不能进去了
在linux里目录也是文件
读目录文件里的内容
读出来的是目录项
一个目录文件内部里面就存储着一条一条目录里的内容
vi一个目录
这些东西就是目录项
11-目录操作函数2
写目录操作几乎不做
就是添加目录项
manpage里面也没有writedir
opendir closedir打开的是目录了 返回的是DIR结构体
opendir.c:
在vim下查看man手册
:!man perror
readir得到是什么
读一次目录 得到一个目录项:
struct dirent结构体就是描述目录项的
d_name 256 指示这文件长度最大不能超过255 还有一个\0呢
读一次调用一次读一条目录项
再调用一次 再读一条目录项
如果想把所有都读出要循环去调用
所以当为null的时候要继续判断errno 如果有值说明程序出错 如果没有值说明到达文件结尾了
12-递归目录
opendir如何实现不打印隐藏文件?
加一行判断 如何文件名的第一个字符不是. 就打印
思考题: 如何实现 ls –l
答:用stat函数拿到inode结构体的内容
stat拿到的是uid和gid 对应的是数, 如果想输出字符串还要自己对应一下
05-Linux系统编程-第02天(文件系统、目录操作、dup2)的更多相关文章
- Linux系统编程(6)——文件系统
计算机的文件系统是一种存储和组织计算机数据的方法,它使得对其访问和查找变得容易,文件系统使用文件和树形目录的抽象逻辑概念代替了硬盘和光盘等物理设备使用数据块的概念,用户使用文件系统来保存数据不必关心数 ...
- Linux系统编程【4】——文件系统
pwd命令的作用 Linux的文件系统比较庞大,所以笔者从pwd这一命令入手,在实现的过程中加深对文件系统的了解. 输入:man pwd 从指导文档中可以看到,pwd命令的作用是显示出当前所处位置,以 ...
- Linux系统编程【2】——编写who命令
学到的知识点 通过实现who命令,学到了: 1.使用man命令寻找相关信息 2.基于文件编程 3.体会到c库函数与系统调用的不同 4.加深对缓冲技术的理解 who命令的作用 who命令的使用 在控制终 ...
- Linux系统编程温故知新系列 --- 01
1.大端法与小端法 大端法:按照从最高有效字节到最低有效字节的顺序存储,称为大端法 小端法:按照从最低有效字节到最高有效字节的顺序存储,称为小端法 网际协议使用大端字节序来传送TCP分节中的多字节整数 ...
- Linux系统编程@进程通信(一)
进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...
- Linux 系统编程
简介和主要概念 Linux 系统编程最突出的特点是要求系统程序员对它们工作的的系统的硬件和操作系统有深入和全面的了解,当然它们还有库和系统调用上的区别. 系统编程分为:驱动编程.用户空间编程和网络编程 ...
- 读书笔记之Linux系统编程与深入理解Linux内核
前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...
- Linux系统编程【转】
转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准 ...
- 《Linux系统编程(第2版)》
<Linux系统编程(第2版)> 基本信息 作者: (美)Robert Love 译者: 祝洪凯 李妹芳 付途 出版社:人民邮电出版社 ISBN:9787115346353 上架时间:20 ...
- linux系统编程(一)概述
glibc库封装了linux系统调用,并提供c语言接口 所以学习linux系统编程,主要参考glibc库系统调用相关api 一.进程控制: fork 创建一个新进程 clone 按指定条件创建子进程 ...
随机推荐
- Linq查询datatable的记录集合
通过linq查询datatable数据集合满足条件的数据集 1.首先定义查询字段的变量,比方深度 string strDepth=查询深度的值: var dataRows = from datarow ...
- The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
完整错误信息: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"AS IS" AND ANY ...
- hdu5242 上海邀请赛 优先队列+贪心
题意是给你一棵树 n个点 n-1条边 起点是1 每一个点都有权值 每次能从根节点走到叶子节点 经行k次游戏 每次都是从1開始 拿过的点的权值不能拿第二次 问最大权值和. 開 ...
- tflearn中计算混淆矩阵方法——需要经过一步转换
def do_rnn_wordbag(trainX, testX, trainY, testY): y_test=testY #trainX = pad_sequences(trainX, maxle ...
- C# SuperWebSocket服务端学习(二)
首先需要下载DLL类库 地址详见:http://download.csdn.NET/detail/u011269801/9590935 1,打开VS2012,新建一个控制台应用程序,选择.NET4. ...
- bzoj 2005 & 洛谷 P1447 [ Noi 2010 ] 能量采集 —— 容斥 / 莫比乌斯反演
题目:bzoj 2005 https://www.lydsy.com/JudgeOnline/problem.php?id=2005 洛谷 P1447 https://www.luogu.org/ ...
- org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.demo.pojo.IdCard
转自:https://blog.csdn.net/zheng0518/article/details/11029733 TestStudent.testSchemaExporttestSchemaEx ...
- 原生JS---4
原生js学习笔记4——BOM操作 什么是DOM DOM:Do 1. js的组成部分 2. 一套标准,目前有DOM1和DOM2这两种标准 我们可以使用DOM操作来操作页面中的元素. DOM节点 子节点 ...
- 网易UI自动化测试工具Airtest中导入air文件中的方法
最近看了一下网易的Airtest ,UI测试工具,写了一些后在导入其他air文件中的.py文件,卡了一下,现在博客中纪录一下导入其他air文件的方式: 在Airtest 测试工具中,导入其他air文件 ...
- indeed 5.13 第二次网测
题目描述,我找不见了,大概写一下想法和代码吧. 1. 没有看 2. 由于数据范围很小,就是简单的枚举,求全排列,然后更新答案. #include<bits/stdc++.h> #defin ...