《Unix/Linux编程实践教程》笔记(3)
Table of Contents
内容
本节主要讲了unix操作系统如何将文件和目录组织起来。文件依靠inode来区分,目录是一个包含文件名和inode的集合,每个目录都有2个特殊的目录 . 和 .. ,它们分别表示当前目录和上一层目录,只有根目录的 . 和 .. 指向同一个目录。
inode中有数据块的编号,数据块储存文件的内容,数据块还有二级,三级之分(不同操作系统的实现不同)。也就是说,当我们打开一个文件,内核会在目录中找到文件相应的inode号,通过inode号找到储存文件的数据块,从数据块中读取文件内容。
与目录相关的系统调用有
- mkdir(pathname, mode) 创建目录
- readir(path) 删除非空目录
- unlink(path) 删除一个链接
- link(orig, new) 创建一个文件的新链接
- rename(from, to) 重命名或删除一个链接
习题
4.15 使mkdir支持递归创建目录
递归创建,即一层层的创建不存在的目录,用系统函数access来探测是否存在目录。具体代码如下:
#include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> int main (int ac, char *av[]) { char pathname[128]; int i, len; memset(pathname, '\0', 128); if (ac == 1) { printf("useage: ./mkdir dirname\n"); exit(-1); } if (ac == 3 && (strcmp(av[1],"-p") == 0) ) { //printf("av[1]is %s\n", av[1]); strcpy(pathname, av[2]); //printf ("pathname is %s", pathname); //if (pathname[0] == '/') // printf ("pathname[0] is %c", pathname[0]); i = 1; len = strlen(pathname); while (i < len -1) { if (pathname[i] == '/') // / 是linux下的目录分割符 { pathname[i] = '\0'; if (access(pathname, F_OK) != 0) //如果目录不存在,则创建 { if (mkdir(pathname, 0755) != 0) { perror ("cannot mkdir"); exit(-1); } printf ("mkdir %s\n", pathname); } pathname[i] = '/'; } i++; } if(mkdir(pathname, 0755) != 0) { perror("cannot mkdir"); exit(-1); } printf ("mkdir %s\n", pathname); } return 0; }
4.16 使rename支持两个参数
使rename支持两个参数,第一个参数必须是文件,第二个可为文件或目录,不会覆盖。代码如下
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <libgen.h> int main (int ac, char *av[]) { struct stat info; char *pathtofile; if (ac != 3) { perror("ac"); exit(-1); } //如果第一个文件不存在,则退出 if (stat(av[1], &info) == -1) { perror("stat"); exit(-1); } if (!S_ISREG(info.st_mode)) { printf ("av[1] must be regular file\n"); exit(-1); } //如果第二个参数不存在于系统 if (stat(av[2], &info) == -1) { //如果dirname存在,则把第二个参数当成文件路径 char *tmpchar = strdup(av[2]); if (stat(dirname(tmpchar), &info) == -1) { perror("stat dirname av[2]"); exit(-1); } if (S_ISDIR(info.st_mode)) { //printf("av[2] is %s", av[2]); rename(av[1], av[2]); } return 0; } //如果第二个参数存在于系统且是目录,类似于cp的处理 if (S_ISDIR(info.st_mode)) { int len = strlen(av[2]); char *filename = basename(av[1]); pathtofile = (char *)malloc(strlen(av[1])+len+2); memset(pathtofile, 0, strlen(filename)+len+2); strcat(pathtofile, av[2]); if (pathtofile[len-1] != '/') strcat(pathtofile, "/"); strcat(pathtofile, filename); rename(av[1], pathtofile); return 0; } else{ //如果第二个参数存在于系统且是文件, 不做操作,退出 if (S_ISREG(info.st_mode)) { printf("%s is existed\n",av[2]); exit(-1); } } return 0; }
项目
结束
本章简单讲了文件系统的内部结构。4.5.2的pwd遇到一个问题,一个文件系统的根的当前目录inode和父目录inode是相同的,然而它并不是/目录。我查看了我当前的linux系统,已经没有这个问题了。