zoukankan      html  css  js  c++  java
  • ch7&ch8学习笔记

    知识点归纳

    一块存储设备,可以分为几个逻辑单元,称为分区。各个分区均开一格式化为特定的文件系统。

    分区表位于第一个扇区的字节偏移446处,该扇区成为设备的主引导记录(MBR)

    如果分区是扩展类型,那么它可以划分为更多的分区

    Linux一直使用EXT2作为默认文件系统,EXT3是EXT2的扩展,增加的主要内容是日志文件

    Block#0 是引导块,文件系统不会使用它,它用于容纳从磁盘引导操作系统的引导程序

    Block#1 是超级块,用于容纳关于整个文件系统的信息

    Block#2 是块组描述符,EXT2将磁盘块分成几个组,每组有8192个块,每组用一个块组描述符结构体描述

    Block#8 是块位图,用于表示某种项的位序列,例如磁盘块或索引节点,位图用于分配和回收项。

    Block#9 是索引节点位图,索引节点用于代表一个文件的数据结构

    Block#10 是索引(开始)节点块,索引节点大小用于平均分割块大小,所以每个索引节点块都包含整数个索引节点。

    数据块 是紧跟在索引节点块后面的文件存储块。

    目录条目:dir_entry结构体{inode,rec_len,name_len,file_type,name}

    内核的系统调用处理程序 根据系统调用编号 将调用路由到一个相应的内核函数。当进程结束执行内核函数时,会返回到用户模式,返回值大于等于0,表示成功,返回值等于-1表示失败。如果失败,errno变量会记录错误编号,它们会被映射到描述错误原因的字符串,使用<errno.h>里的strerror()函数。

    常用的系统调用有

    系统调用 作用
    stat(fstat,lstat) 获取文件状态信息
    open 打开文件
    close 关闭打开的文件描述符
    read 读取文件
    write 写入文件
    lseek 重定位偏移量
    dup 将文件描述符复制到可用的最小描述符编号中
    dup2 将旧文件描述符 复制到新文件描述符
    link 将新文件硬链接到旧文件
    unlink 取消链接,如果链接数为0,则删去文件
    symlink 创建一个符号链接
    readlink 读取符号链接文件的内容
    umask 设置文件创建掩码

    链接文件:分为硬链接和软链接。软链接相当于windows里的快捷方式,硬链接文件会共享文件系统中相同的索引节点(inode)

    lstat会返回链接文件本身的信息

    stat结构体

    struct stat{
        dev_t    st_dev ;        / * device * /
        ino_t    st_ino;        / * inode * /  
        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 type (if inode device)*/
        off_t    st_size;      /* total size, in bytes * /
        u32      st_blksize;    / * blocksize for filesystem I/O */
        u32      st_blocks;      / *number of blocks allocated*/
        time_t   st_atime;      / * time of last access */
        time_t   st_mtime;    /* time of last modification */
        time_t   st_ctime;    /* time of last change * /
    };
    

    st_mode与宏函数

    索引节点结构体

    struct ext2_inode{
        u16     i_mode;
        u16     i_uid;
        u32     i_size;
        u32     i_atime;
        u32     i_ctime;
        u32     i_mtime;
        u32     i_dtime;
        u16     i_gid;
        u16     i_links_count;
        u32     i_blocks;
        u32     i_flags;
        u32     i_reserved1 ;
        u32     i_block[15];
        u32     pad[7];
    }
    

    更多关于st_mode,点击这里

    目录也是一个文件,我们应该能像其他普通文件一样,打开一个目录,然后读写它的内容。<dirent.h> opendir()和readdir()

    问题与解决思路

    • 由用户ID获取用户名

    ID => struct passwd => .pw_name

          //uid
          struct passwd *user;
          user = getpwuid(fstat.st_uid);
          printf("%s	",user->pw_name);
    
    
    • 用组ID获取组名

    ID => struct group => .gr_name

          // gid
          struct group *gdata;
          gdata = getgrgid(fstat.st_gid);
          printf("%s  ", gdata->gr_name);
    
    • 删除路径中的目录,获得文件名
    char *basename(char *path);
    
    char *filename = basename(path);
    
    
    • 格式化输出st_mtime
    struct tm *localtime(const time_t *timer)
    
    struct tm {
       int tm_sec;         /* 秒,范围从 0 到 59                */
       int tm_min;         /* 分,范围从 0 到 59                */
       int tm_hour;        /* 小时,范围从 0 到 23                */
       int tm_mday;        /* 一月中的第几天,范围从 1 到 31                    */
       int tm_mon;         /* 月份,范围从 0 到 11                */
       int tm_year;        /* 自 1900 起的年数                */
       int tm_wday;        /* 一周中的第几天,范围从 0 到 6                */
       int tm_yday;        /* 一年中的第几天,范围从 0 到 365                    */
       int tm_isdst;       /* 夏令时                        */    
    };
    

    实践内容

    比较系统调用和库函数的速度

    输出目录下的文件(不递归进入目录)

      1 #include <dirent.h>
      2 #include <stdio.h>
      3 
      4 int main(int argc,char *argv[]){
      5     struct dirent *ep ;
      6     DIR *dp = opendir(argv[1]);
      7     while (ep = readdir(dp) ){
      8         printf( "%s  ", ep->d_name);
      9     }
     10     printf("
    ");
     11     return 0;
     12 }
    

    ls-l实现——myll

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <sys/stat.h>
      5 #include <time.h>
      6 #include <sys/types.h>
      7 #include <dirent.h>
      8 #include <unistd.h>
      9 #include <libgen.h>
     10 #include <pwd.h>
     11 #include <grp.h>
     12 
     13 int ls_file(char *fname){
     14     //get file status
     15     struct stat fstat;
     16     int r, i;
     17     char ftime[64];
     18     if((r = lstat(fname,&fstat)) < 0){
     19         perror("lstat file failed ");
     20         exit(1);
     21     }
     22     //get file type
     23     if(S_ISREG(fstat.st_mode)){
     24         printf( "%c" ,'-' ) ;
     25     }else if (S_ISDIR(fstat.st_mode)){
     26         printf ( "%c" ,'d' ) ;
     27     }else if (S_ISLNK(fstat.st_mode)){
     28         printf ( "%c",'l') ;
     29     }else if (S_ISCHR(fstat.st_mode)){
     30         printf ( "%c",'c') ;
     31     }else if (S_ISFIFO(fstat.st_mode)){
     32         printf ( "%c",'p') ;
     33     }else if (S_ISSOCK(fstat.st_mode)){
     34         printf ( "%c",'s') ;
     35     }else if (S_ISBLK(fstat.st_mode)){
     36         printf ( "%c",'b') ;
     37     }else{
     38         //unknown type
     39         printf ( "%c",'?') ;
     40     }
     41    
     42     //get file rwx
     43     char *t1 = "rwxrwxrwx";
     44     for (i=8; i>= 0; i--){
     45         if (fstat.st_mode & (1 << i))       //print rwx
     46             printf("%c", t1[8-i]);
     47         else
     48             printf("%c", '-');
     49     }
     50    
     51     printf("%4d " , fstat.st_nlink);            // link count
     52 
     53     //uid
     54     struct passwd *user;
     55     user = getpwuid(fstat.st_uid);
     56     printf("%s	",user->pw_name);
     57    
     58     // gid
     59     struct group *gdata;
     60     gdata = getgrgid(fstat.st_gid);
     61     printf("%s  ", gdata->gr_name);
     62 
     63     printf("%8d " , fstat.st_size) ;        // file size
     64     // print time
     65     //strcpy(ftime,ctime(fstat.st_ctime)) ;  //print time in calendar form
     66     //ftime[strlen(ftime)-1] = 0;               // kill in at end
     67     //printf ("%s ",ftime);             //print name
     68     //printf ("%s",basename(fname)) ;   // print file basename
     69     struct tm *block;
     70     block = localtime(&fstat.st_mtime);
     71     printf("%4d-%02d-%02d %02d:%02d ",
     72         block->tm_year+1900, block->tm_mon+1, block->tm_mday,
     73         block->tm_hour, block->tm_min);
     74 
     75     //print name
     76     printf("%s",basename(fname));
     77     // print -> linkname if symbolic file
     78     if (S_ISLNK(fstat.st_mode)){
     79         char buf[100];
     80         int result = readlink(fname,buf,100-1);
     81         if (result < 0){
     82             perror("readlink ");
     83             exit(1);
     84         }
     85         printf(" -> %s",buf);   //print link file content
     86     }
     87     printf("
    ");
     88 }
     89 
     90 int ls_dir(char *dname){
     91     //use opendir( ), readdir( ) ; then ca11 1s_file(name)
     92     DIR *dp;
     93     struct dirent *sdp;
     94     dp = opendir(dname);
     95     if(dp==NULL){
     96         perror("opendir failed ");
     97         exit(1);
     98     }
     99     int len = strlen(dname);
    100     while( (sdp = readdir(dp)) != NULL){
    101         if(sdp->d_name[0]=='.'){
    102             continue;
    103         }
    104         char filename[1024];
    105         int i;
    106         for(i=0;i<len;i++){
    107             filename[i] = dname[i];
    108         }
    109         filename[len] = '/';
    110         len++;
    111         for(i=0;sdp->d_name[i]!='';i++){
    112             filename[i+len]=sdp->d_name[i];
    113         }
    114         filename[i+len]='';
    115         len--;
    116         ls_file(filename);
    117     }
    118     closedir(dp);
    119 }
    120 
    121 int main (int argc, char *argv[]){
    122     //get file status
    123     struct stat sbuf;
    124     int r;
    125     char cwd[1024];
    126     getcwd(cwd,1023);
    127     char *route = strcat(cwd,"/");
    128     if(argc == 2){
    129         route = strcat(cwd,argv[1]);
    130     }
    131     r = lstat(route,&sbuf);
    132     if(r<0){
    133         perror("lstat ");
    134         exit(1);
    135     }
    136 
    137     //
    138     if(S_ISDIR(sbuf.st_mode)){
    139         ls_dir(route);
    140     }else{
    141         ls_file(route);
    142     }
    143     return 0;
    144 }
    
    

    rm-r实现——remove_dir

      1 #include <sys/stat.h>
      2 #include <dirent.h>
      3 #include <fcntl.h>
      4 #include <stdlib.h>
      5 #include <stdio.h>
      6 #include<sys/types.h>
      7 #include <string.h>
      8 #include <unistd.h>
      9 
     10 int remove_dir(const char *dir)
     11 {
     12     char cur_dir[] = ".";
     13     char up_dir[] = "..";
     14     char dir_name[128];
     15     DIR *pdir;
     16     struct dirent *dp;
     17     struct stat dir_stat;
     18 
     19     // 参数传递进来的目录不存在,直接返回
     20     if (access(dir, F_OK)==-1) {
     21         return 0;
     22     }
     23 
     24     // 获取目录属性失败,返回错误
     25     if (stat(dir, &dir_stat)<0) {
     26         perror("get directory stat error");
     27         return -1;
     28     }
     29 
     30     if (S_ISREG(dir_stat.st_mode) ) {  // 普通文件直接删除
     31         remove(dir);
     32     } else if (S_ISDIR(dir_stat.st_mode) ) {   // 目录文件,递归删除目录中内容
     33         pdir = opendir(dir);
     34         while ((dp=readdir(pdir)) != NULL ) {
     35             // 忽略 . 和 ..
     36             if ( (0 == strcmp(cur_dir, dp->d_name)) || (0 == strcmp(up_dir, dp->d_name)) ) {
     37                 continue;
     38             }
     39             sprintf(dir_name, "%s/%s", dir, dp->d_name);
     40             remove_dir(dir_name);   // 递归调用
     41         }
     42         closedir(pdir);
     43         rmdir(dir);    // 删除空目录
     44     } else {
     45         perror("unknow file type!");
     46         exit(1);
     47     }
     48 }
     49 int main(int argc,char *argv[]){
     50     remove_dir(argv[1]);
     51     return 0;
     52 }
    
    

    创建符号链接(软链接)

      1 #include <unistd.h>
      2 
      3 int main()
      4 {
      5     symlink("./myll.c","slink");
      6     return 0;
      7 }
    

    实现cp-r

    #include <stdio.h> 
    #include <string.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <libgen.h>
    #include <sys/types.h> 
    #include <dirent.h>
    #include <fcntl.h>
    #define BLOCK 4096
    
    int ftype(char *path){
    	if(access(path,F_OK)==-1){
    		//文件不存在
    		return -1; 
    	}else{
    		//文件存在
    		struct stat sbuf;
    		if(lstat(path,&sbuf) < 0){
    			perror("lstat ");
    			exit(1);
    		}
    		if(S_ISREG(sbuf.st_mode)){
    			return 1; 
    		}else if(S_ISDIR(sbuf.st_mode)){
    			return 2; 
    		}else if(S_ISLNK(sbuf.st_mode)){
    			return 3; 
    		}
    	}
    	return 0; 
    }
    
    void toslink(int fd){
    	//change reg file to soft link
    }
    
    int remove_dir(const char *dir)
    {
        char cur_dir[] = ".";
        char up_dir[] = "..";
        char dir_name[128];
        DIR *pdir;
        struct dirent *dp;
        struct stat dir_stat;
    
        // 参数传递进来的目录不存在,直接返回
        if (access(dir, F_OK)==-1) {
            return 0;
        }
    
        // 获取目录属性失败,返回错误
        if (stat(dir, &dir_stat)<0) {
            perror("get directory stat error");
            return -1;
        }
    
        if (S_ISREG(dir_stat.st_mode) ) {  // 普通文件直接删除
            remove(dir);
        } else if (S_ISDIR(dir_stat.st_mode) ) {   // 目录文件,递归删除目录中内容
            pdir = opendir(dir);
            while ((dp=readdir(pdir)) != NULL ) {
                // 忽略 . 和 ..
                if ( (0 == strcmp(cur_dir, dp->d_name)) || (0 == strcmp(up_dir, dp->d_name)) ) {
                    continue;
                }
                sprintf(dir_name, "%s/%s", dir, dp->d_name);
                remove_dir(dir_name);   // 递归调用
            }
            closedir(pdir);
            rmdir(dir);    // 删除空目录
        } else {
            perror("unknow file type!");
            exit(1);
        }
        return 1; 
    }
    
    void file2file(char *src,char *des){
    	//打开src,只读 
    	int fd1 = open(src,O_RDONLY);
    	if(fd1<0){
    		perror("open src file error");
    		exit(1);
    	}
    	//打开des,如果存在,截断;如果不存在,创建 
    	int fd2 = open(des,O_WRONLY|O_CREAT|O_TRUNC,0644);
    	if(fd2<0){
    		perror("open dest file error");
    		exit(1);
    	}
    	//读src到buf,把buf写入des
    	char buf[BLOCK];
    	if(ftype(src)==3){		//复制软链接 
    		int len = readlink(src,buf,sizeof(buf));
    		write(fd2,buf,len);
    		toslink(fd2);
    	}else{					//复制普通文件 
    		int n;
    		while(n=read(fd1,buf,sizeof(buf))){
    			write(fd2,buf,n);
    		}
    	}
    	//关闭文件
    	close(fd1);
    	close(fd2);
    	 
    }
    void file2dir(char *src,char *des){
    	//改一下文件路径,在结尾加上src的文件名
    	char newpath[256];
    	sprintf(newpath,"%s/%s",des,basename(src));
    	//转变为file2file 
    	file2file(src,newpath); 
    }
    
    void dir2dir(char *src,char *des){
    	//打开目录src
    	DIR *dp1;
    	dp1 = opendir(src);
    	if(dp1==NULL){
    		perror("open src dir error");
    		exit(1);
    	}
    	//打开目录des
    	if(ftype(des)==-1){
    		//如果des不存在,创建 
    		if(mkdir(des,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH)<0){
    			perror("mkdir failed");
    			exit(1);
    		}
    	}else if(ftype(des)==2){
    		//如果存在des,删除该目录,重新创建 
    		remove_dir(des);
    		if(mkdir(des,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH)<0){
    			perror("mkdir failed");
    			exit(1);
    		}
    	}
    	struct dirent *srcdp;
    	//遍历src目录项
    	while((srcdp = readdir(dp1)) != NULL){
    	    if(srcdp->d_name[0] == '.'){//跳过隐藏文件
    			continue;
    		}
    		//拼接目录项路径 
    		char newsrc[256];
    		sprintf(newsrc,"%s/%s",src,srcdp->d_name);
    		char newdes[256];
    		sprintf(newdes,"%s/%s",des,srcdp->d_name);
    
    		if(ftype(newsrc)==2){ //如果目录项是目录 
    			dir2dir(newsrc,newdes); 
    		}else{				//如果目录项是文件
    			file2file(newsrc,newdes);
    		}
    	}
    }
    int main(int argc,char *argv[]){
    	//获取命令行参数,
        //printf("argc = %d
    ",argc);
    	if(argc!=3){
    		printf("命令格式错误
    ");
    		exit(1);	
    	}
    	
    	char src[256],des[256];
    	char cwd[128];
    	getcwd(cwd,sizeof(cwd));
    	sprintf(src,"%s/%s",cwd,argv[1]);
    	sprintf(des,"%s/%s",cwd,argv[2]);
    	
    	//如果src = des ,不用复制,直接退出
    	if(strcmp(src,des)==0){
    		exit(1);
    	} 
    	//判断是哪一种,获取文件状态,
    	if(ftype(src)==2){		//src is dir
    		if(ftype(des)==2){
    			//目标目录存在,src成为其子文件夹
    			sprintf(des,"%s/%s",des,basename(src));
    			dir2dir(src,des);
    		}else if(ftype(des) == -1){
    			//目标目录不存在,创建目录
    			dir2dir(src,des);
    		}else{
    			printf("不能将目录复制到文件
    ");
    			exit(1);
    		}
    	}else if(ftype(src)==1 || ftype(src)==3){	//src is file
    		if(ftype(des)==2){
    			file2dir(src,des);
    		}else{
    			file2file(src,des);
    		}
    	}
    	return 0;
    }
    
    

    新增

    补充实现cp-r复制软链接(符号链接)
    改进file2file函数

     75 void file2file(char *src,char *des){
     76     //复制软链接
     77     char buf[BLOCK];
     78     memset(buf,sizeof(buf),0);
     79     if(ftype(src)==3){      //复制软链接 
     80         int len = readlink(src,buf,sizeof(buf));
     81         buf[len]='';      //buf里面有多余的字符,00截断
     82         symlink(buf,des);
     83         return;
     84     }
     85     //打开src,只读 
     86     int fd1 = open(src,O_RDONLY);
     87     if(fd1<0){
     88         perror("open src file error");
     89         exit(1);
     90     }
     91     //打开des,如果存在,截断;如果不存在,创建 
     92     int fd2 = open(des,O_WRONLY|O_CREAT|O_TRUNC,0644);
     93     if(fd2<0){
     94         perror("open dest file error");
     95         exit(1);
     96     }
     97 
     98     int n;
     99     while(n=read(fd1,buf,sizeof(buf))){
    100         write(fd2,buf,n);
    101     }
    102     //关闭文件
    103     close(fd1);
    104     close(fd2);
    105 
    106 }
    
    

  • 相关阅读:
    dbvisualizer free 9.5.6中文乱码
    Tomcat下编译没哟class源文件
    Microsoft Visual C++ Runtime error解决方法
    eclispe中svn插件的安装和使用教程(二)
    eclipse安装SVN插件的两种方法(一)
    解决eclipse中配置Tomcat中没有server选项
    【原创精品】mac 彻底卸载趋势科技
    【原创】beyond compare 解决文件一样,对比有差异的问题
    Git各大平台(win/Linux/Mac)图形化界面客户端大汇总
    【原创】用python连接thrift Server 去执行sql的问题总汇
  • 原文地址:https://www.cnblogs.com/cfqlovem-521/p/15362070.html
Copyright © 2011-2022 走看看