IO的效率问题
习题:
设置不同的BUFSIZE,查看mycp命令所耗的时间。BUFSIZE[128-16M],3-5GB大小的文件
出具表格,realtime,usertime,systime,循环次数,分析拐点,以及何时出错。
文件共享:多个任务共同操作一个文件或者协同完成任务。
面试题:写程序(使用系统IO)删除一个文件的第10行。
补充函数:truncate/ftruncate
方法一、
while(){
lseek 11
read
lseek 10
write
}
====================================
方法二、对同一个文件打开两次
open r fd1 lseek 11
open r+ fd2 lseek10
fd1 read
fd2 write
方法三、多进程或多线程
一个读、一个写
原子操作
不可分割的最小单位
原子操作:不可分割的操作。
原子操作的作用:解决竞争和冲突。
如tmpnam
dup、dup2
同步
sync:同步内核buffer cache至磁盘
fsync:
fdatasync:之刷新非元数据
fcntl函数
管家级函数
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
ioctl函数
管理所有设备相关的内容
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
/dev/fd/ 虚目录
当前进程的文件描述符信息,类似照镜子,谁看就是谁的。
文件系统
类似ls的实现,myls命令
command -短格式 --长格式 param1,param2 ...
一、目录(会用到递归)和文件
- 如何获取文件属性?
stat,fstat,lstat - 如何控制文件的访问权限
mode_t,16位bitmap,表示文件类型,文件访问权限,以及特殊权限位 - umask
- 如何更改文件权限/管理?
- 什么是粘着位?
- 文件系统FAT ,UFS是什么东西?
- 什么是硬链接,符号链接?
- utime
- 目录的创建和销毁
mkdir、rmdir - 更改当前工作路径
chdir、fchdir - 分析目录/读取目录内容
二、系统数据文件和信息
三、当前的进程环境
stat
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf); //获取文件属性信息,填到buf
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
struct stat {
dev_t st_dev; /* ID of device containing file */ 包含当前文件的设备ID号
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */ 文件类型和权限
nlink_t st_nlink; /* Number of hard links */ 硬链接数
uid_t st_uid; /* User ID of owner */ UID
gid_t st_gid; /* Group ID of owner */ GID
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */ 总字节数
blksize_t st_blksize; /* Block size for filesystem I/O */ 块大小
blkcnt_t st_blocks; /* Number of 512B blocks allocated */ 多少个512块
/* 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
};
stat函数使用
#include <stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static off_t flen(const char *fname){
struct stat statres;
if(stat(fname,&statres)<0){
perror("stat error");
exit(1);
}
return statres.st_size;
}
int main(int argc, char const *argv[])
{
if (argc<2)
{
fprintf(stderr,"Usage....\n");
exit(1);
}
printf("total size: %ld ",flen(argv[1]));
exit(0);
}
写程序做一个大文件
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(int argc, char const *argv[])
{
int fd;
if (argc<2)
{
fprintf(stderr,"Usages....");
exit(1);
}
fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0600);
if (fd<0)
{
perror("open()");
exit(1);
}
lseek(fd,5LL*1024LL*1024LL*1024LL-1LL,SEEK_SET); //int型会溢出
write(fd,"",1);
close(fd);
exit(0);
}
Size:文件大小
Blocks:占用空间
mode_t
struct stat {
dev_t st_dev; /* ID of device containing file */ 包含当前文件的设备ID号
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */ 文件类型和权限
...
}
mode_t 以bitmap形式存储,16位
文件类型7种,user,group,others,u+s,g+s,粘着位
3位 9位 3位 一共15位
所以需要一个16位的bitmap来存储
文件类型:dcb-lsp
d
目录
c
字符设备文件
b
块文件
-
普通文件
l
符号连接(硬链接)
s
网络套接字
p
管道文件(命名管道)
示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
static int ftype(const char *fname){
struct stat statres;
if(stat(fname,&statres)<0){
perror("stat()");
exit(1);
};
if(S_ISREG(statres.st_mode)) return '-';
if(S_ISDIR(statres.st_mode)) return 'd';
if(S_ISCHR(statres.st_mode)) return 'c';
if(S_ISBLK(statres.st_mode)) return 'b';
if(S_ISFIFO(statres.st_mode)) return 'p';
if(S_ISLNK(statres.st_mode)) return 'l';
if(S_ISSOCK(statres.st_mode)) return 's';
return '?';
}
int main(int argc, char const *argv[])
{
if(argc<2 ){
fprintf(stderr,"Usage......\n");
exit(1);
}
printf("the type of %s is %c\n",argv[1],ftype(argv[1]));
exit(0);
}
权限bitmap,上图为八进制数
16位整型数
1111 000 000 000 000 S_IFMT
1100 000 000 000 000 S_IFSOCK
1010 000 000 000 000 S_IFLINK
1000 000 000 000 000 S_IFREG
0110 000 000 000 000 S_IFBLK
0100 000 000 000 000 S_IFDIR
0010 000 000 000 000 S_IFCHR
0001 000 000 000 000 S_IFIFO
0000 100 000 000 000 S_ISUID 设置UID
0000 010 000 000 000 S_ISGID 设置GID
0000 001 000 000 000 S_ISVTX 粘着位
0000 000 111 000 000 S_IRWXU
0000 000 100 000 000 S_IRUSR
0000 000 010 000 000 S_IWUSR
0000 000 001 000 000 S_IXUSR
0000 000 000 111 000 S_IRWXG
0000 000 000 100 000 S_IRGRP
0000 000 000 010 000 S_IWGRP
0000 000 000 001 000 S_IXGRP
0000 0000 00 000 111 S_IRWXO
0000 000 000 000 100 S_IROTH
0000 000 000 000 010 S_IWOTH
0000 000 000 000 001 S_IXOTH
umask函数
防止产生权限过松的文件
umask - set file mode creation mask
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
文件权限更改
chmod、fchmod
NAME
chmod, fchmod, fchmodat - change permissions of a file
SYNOPSIS
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
粘着位
又称t位,
原本的作用:给某一个可执行的二进制命令设置t位,作用是保留命令的使用痕迹,下次装载模块是会比较快。
现在的作用:各个用户对目录的操作特殊化
文件系统FAT
文件系统:文件或数据的存储和管理。
FAT不开源,UFS开源
FAT文件系统核心:
FAT16/32:静态存储的单链表(array),单链表单向的,一式两份,出现差错无法定位哪个哪一份错误
文件系统UFS
文件名在目录文件中
面试题:要求使用bitmap。
①封装一个函数,比较两个32位无符号整数的大小,返回较大的那个数,要求不能使用比较和判断。
②一个无符号32位整数,例如93,它的二进制形式里有多少个0?多少个1?
使用移位判断,或者使用bitmap
硬链接
硬链接是目录项的同义词。
ln给文件做硬链接,其实就是在目录文件中写入一个目录项,这个目录项的inode与源文件的inode值一样
- 硬链接与目录项是同义词
- 不能给分区、目录建立硬链接
- 符号链接可以跨分区,可以给目录建立
lry@ubuntu:~/codes/fs$ stat cool
File: cool
Size: 5368709120 Blocks: 8 IO Block: 4096 regular file
Device: 805h/2053d Inode: 2883778 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ lry) Gid: ( 1000/ lry)
Access: 2021-10-02 11:00:22.490656951 +0800
Modify: 2021-10-02 10:59:00.306109455 +0800
Change: 2021-10-02 10:59:00.306109455 +0800
Birth: -
lry@ubuntu:~/codes/fs$ ln cool cool_link
lry@ubuntu:~/codes/fs$ stat cool
File: cool
Size: 5368709120 Blocks: 8 IO Block: 4096 regular file
Device: 805h/2053d Inode: 2883778 Links: 2
Access: (0664/-rw-rw-r--) Uid: ( 1000/ lry) Gid: ( 1000/ lry)
Access: 2021-10-02 11:00:22.490656951 +0800
Modify: 2021-10-02 10:59:00.306109455 +0800
Change: 2021-10-02 15:09:01.247004439 +0800
Birth: -
lry@ubuntu:~/codes/fs$ stat cool_link
File: cool_link
Size: 5368709120 Blocks: 8 IO Block: 4096 regular file
Device: 805h/2053d Inode: 2883778 Links: 2
Access: (0664/-rw-rw-r--) Uid: ( 1000/ lry) Gid: ( 1000/ lry)
Access: 2021-10-02 11:00:22.490656951 +0800
Modify: 2021-10-02 10:59:00.306109455 +0800
Change: 2021-10-02 15:09:01.247004439 +0800
符号链接symbolic link
类似Windows下的快捷方式。
lry@ubuntu:~/codes/fs$ stat cool
File: cool
Size: 5368709120 Blocks: 8 IO Block: 4096 regular file
Device: 805h/2053d Inode: 2883778 Links: 2
Access: (0664/-rw-rw-r--) Uid: ( 1000/ lry) Gid: ( 1000/ lry)
Access: 2021-10-02 11:00:22.490656951 +0800
Modify: 2021-10-02 10:59:00.306109455 +0800
Change: 2021-10-02 15:09:01.247004439 +0800
Birth: -
lry@ubuntu:~/codes/fs$ ln -s cool cool_s_l
lry@ubuntu:~/codes/fs$ stat cool
File: cool
Size: 5368709120 Blocks: 8 IO Block: 4096 regular file
Device: 805h/2053d Inode: 2883778 Links: 2
Access: (0664/-rw-rw-r--) Uid: ( 1000/ lry) Gid: ( 1000/ lry)
Access: 2021-10-02 11:00:22.490656951 +0800
Modify: 2021-10-02 10:59:00.306109455 +0800
Change: 2021-10-02 15:09:01.247004439 +0800
Birth: -
lry@ubuntu:~/codes/fs$ stat cool_s_l
File: cool_s_l -> cool
Size: 4 Blocks: 0 IO Block: 4096 symbolic link
Device: 805h/2053d Inode: 2883783 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ lry) Gid: ( 1000/ lry)
Access: 2021-10-02 15:19:19.744663266 +0800
Modify: 2021-10-02 15:18:55.340616457 +0800
Change: 2021-10-02 15:18:55.340616457 +0800
Birth: -
函数link unlink
man 2 link
NAME
link, linkat - make a new name for a file
SYNOPSIS
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
man 2 unlink
NAME
unlink, unlinkat - delete a name and possibly the file it refers to
SYNOPSIS
#include <unistd.h>
int unlink(const char *pathname);
函数remove
man remove
NAME
remove - remove a file or directory
SYNOPSIS
#include <stdio.h>
int remove(const char *pathname);
函数rename
NAME
rename, renameat, renameat2 - change the name or location of a file
SYNOPSIS
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
时间utime
更改文件的最后访问时间和最后修改时间
NAME
utime, utimes - change file last access and modification times
SYNOPSIS
#include <sys/types.h>
#include <utime.h>
int utime(const char *filename, const struct utimbuf *times);
struct utimbuf {
time_t actime; /* access time */
time_t modtime; /* modification time */
};
假根技术chroot
chdir、fchdir可以突破假根技术,chroot穿越
chdir
fchdir
getcwd
函数glob();
opendir();
closedir();
readdir();
rewinddir();
seekdir();
telldir();
man glob
NAME
glob, globfree - find pathnames matching a pattern, free memory from glob()
SYNOPSIS
#include <glob.h>
int glob(const char *pattern, int flags,
int (*errfunc) (const char *epath, int eerrno),
glob_t *pglob);
void globfree(glob_t *pglob);