7

《Unix/Linux编程实践教程》笔记(3)

 3 years ago
source link: https://houye.xyz/2017-12/uup3/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

《Unix/Linux编程实践教程》笔记(3)

本节主要讲了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系统,已经没有这个问题了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK