第七章
文件操作级别
硬件级别
- fdisk
- mkfs
- fsck
- 碎片整理
操作系统内核中的文件系统函数
系统调用
I/O库函数
用户命令
sh脚本
文件I/O操作
低级别文件操作
分区
-
Command (m for help): m ---输出帮助信息
-
Command action
-
a toggle a bootable flag ---设置启动分区
-
b edit bsd disklabel ---编辑分区标签
-
c toggle the dos compatibility flag
-
d delete a partition --删除一个分区
-
l list known partition types --列出分区类型
-
m print this menu --帮助
-
n add a new partition --建立一个新的分区
-
o create a new empty DOS partition table --创建一个新的空白DOS分区表
-
p print the partition table ---打印分区表
-
q quit without saving changes ---退出不保存设置
-
s create a new empty Sun disklabel ---
-
t change a partition's system id ---改变分区的ID
-
u change display/entry units ---改变显示的单位
-
v verify the partition table ---检查验证分区表
-
w write table to disk and exit ---保存分区表
-
x extra functionality (experts only)
格式划分区
挂载分区
dd if=/dev/zero of =vdisk bs=1024 count=32768
losetup -o $(expr 2048 \* 512) --sizelimit $(expr 65535\* 512) /dev/loop1 vdisk
第八章
系统调用
系统调用手册页
man 2 stat
man 2 open
man 2 read
使用系统调用进行文件操作
#include<stdio.h>
#include<errno.h>
int main()
{
char buf[256],*s;
int r;
r = mkdir("newdir",0766); //mkdir syscall
if(r<0)
printf("error=%d : %s\n",errno,strerror(errno));
r = chdir("newdir"); //cd into newdir
s = getcwd(buf,256); //get CWD string int buf[]
printf("CWD = %s\n",s);
}
常用的系统调用
- open:打开一个文件进行读、写、追加
int open(char *file, int flags, int mode);
- close:关闭打开的文件描述符
int close(int fd);
- read:读取打开的文件描述符
int read(int fd, char buf[], int count);
- write:写入打开的文件描述符
int write(int fd, char buf[], int count);
- dup:将文件描述符复制到可用的最小描述符编号中
int dup(int oldfd);
- dup2:将oldfd复制到newfd中,如果文件链接数为0,则删除文件
int dup2(int oldfd, int newfd);
- link:将新文件硬链接到旧文件
int link(char *oldPath, char *newPath);
- unlink:取消某个文件的链接;如果文件链接数为0,则删除文件
int unlink(char *pathname);
- symlink:创建一个符号链接
int symlink(char *target, char *newpath);
- readlink:读取符号链接文件的内容
int readlink(char *path, char *buf, int bufsize);
- umask:设置文件创建掩码;文件权限为(mask & ~umask)
int umask(int umask);
- mknod:创建特殊文件
int mknod(char *path,int mode,int device)
链接文件
硬链接文件
ln oldpath newpath
对应系统调用:link(char *oldpath,char *newpath)
减少文件链接数:unlink(char *pathname)
符号链接文件
ln -s oldpath newpath
创建符号链接或软链接
symlink(char *oldpath,char *newpath)
- 问题:软链接和硬链接到底有什么区别?
- ChatGPT
stat系统调用
stat文件状态
stat结构体
stat与文件索引节点
每个索引节点在存储设备上都有唯一的索引节点编号(ino)。每个设备都由一对设备号标识,例如0x0302表示/dev/hda2等
文件类型和权限
st_mode:第一个字母表示文件类型,后面9个字符基于权限位,如果位是1,每个字符打印为r|w|x;如果位是0,则打印-。x位表示是否允许访问目录。
opendir-readdir函数
头文件:#include<dirent.h>
具体实现:
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
readlink函数
int readlink(char *pathname,char buf[],int bufsize);
将符号链接文件的内容复制到bufsize的buf[]中,并将实际复制的字节数返回。
ls程序
部分代码:
void printDir(const char* d_name)
{
struct stat statBuf;
char mode[11];
char uidName[10];
char gidName[10];
char lastChgStatTime[30];
memset(mode, 0, 11);
memset(uidName, 0, 10);
memset(gidName, 0, 10);
memset(lastChgStatTime, 0, 30);
if(printall != 1){
if((strcmp(d_name, ".") == 0) || (strcmp(d_name, "..") == 0)){
return;
}
if(d_name[0] == '.'){
return;
}
}
if(0 == lstat(d_name, &statBuf)){
if(printdetail != 1){
printf("%-s\n", d_name);
}else{
/*获取rwxrwxrwx形式的访问权限表示*/
mode2string(statBuf.st_mode, mode);
/*获取uid,gid对应的名称*/
strncpy(uidName, uid2name(statBuf.st_uid), strlen(uid2name(statBuf.st_uid)));
strncpy(gidName, gid2name(statBuf.st_gid), strlen(gid2name(statBuf.st_gid)));
/*time_t转为可读字符串*/
strncpy(lastChgStatTime, time2string(statBuf.st_ctime), strlen(time2string(statBuf.st_ctime)));
/*文件信息打印,没有把struct stat中的信息全部打印*/
printf("%-10s ", mode);
printf("%3d ", statBuf.st_nlink);
printf("%s ", uidName);
printf("%s ", gidName);
printf("%10dB ", statBuf.st_size);
printf("%s ", lastChgStatTime);
printf("%-s\n", d_name);
}
}else{
err_sys("cant't get attribute");
}
}
open-close-lseek系统调用
上面涉及过,在此不做详细叙述
read()系统调用
将n个字节从打开的文件描述符读入用户空间中的buf[] 返回值是实际读取的字节数,read失败返回-1
write()系统调用
将n个字节从用户空间中的buf[]写入文件描述符,必须打开该文件描述符进行写,读写或追加
实践
- 使用系统调用递归复制文件
代码已托管
int copy(char *read_dir_path, char *write_dir_path)
{
DIR * p_dir;
struct dirent * p_dirent;
char read_buf[256];
char write_buf[256];
sprintf(read_buf,"%s/", read_dir_path);
sprintf(write_buf,"%s/",write_dir_path);
strcat(read_dir_path,"/");
if( Is_dir(read_buf) )
{
//mkdir
if(mkdir(write_buf, 0755) < 0)
{
printf("mkdir fall:%s\n", strerror(errno));
return -1;
}
//opendir and readdir
if((p_dir = opendir(read_buf)) == NULL )
{
printf("Usage:cp -r <src_dir> <dat_dir> error:%s\n",strerror(errno));
return -1;
}
while((p_dirent=readdir(p_dir)) != NULL)
{
char read_buffer[256];
char write_buffer[256];
sprintf(read_buffer,"%s%s", read_buf, p_dirent->d_name);
sprintf(write_buffer,"%s%s", write_buf, p_dirent->d_name);
printf("%s\n%s\n",read_buffer,write_buffer);
//it is a directory
if( Is_dir(read_buffer) && 0 != strcmp(p_dirent->d_name, ".") && 0 != strcmp(p_dirent->d_name, "..") )
{
copy_r(read_buffer, write_buffer);
}
else if(0 != strcmp(p_dirent->d_name, ".") && 0 != strcmp(p_dirent->d_name, ".."))
{
//copy file
if( file_copy_line(read_buffer, write_buffer) < 0 )
return 0;
}
}
closedir(p_dir);
}
}
苏格拉底挑战
-
软链接
-
write()系统调用