Linux系统开发 3 文件系统开发 文件/目录

本文谢绝转载,原文来自http://990487026.blog.51cto.com


Linux系统开发
	文件操作
		ext2文件系统了解
		stat()函数
		access()函数
		chmod()函数
		utime()函数
		truncate()函数
		link()硬链接函数
		symlink()软链接函数
		readlink()函数
		unlink函数
		rename函数()
	目录操作
		chdir()/fchdir()
		getcwd/getwd()/get_current_dir_name()
		pathconf()
		opendir()  
		readdir()
		dup()/dup2()

	练习:	

深入解析 ext2 文件系统

stat函数获取文件大小

[email protected]:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
//#include <fcntl.h>

int main(int argc,char **argv)
{
	struct stat s_buf;
	if(argc < 2)
	{
		printf("参数不够\n");
		exit(1);
	}
	if(stat(argv[1],&s_buf) < 0)
	{
		perror("stat");
		exit(2);
	}
	printf("文件名:%s\n",argv[1]);
	printf("文件大小:%ld字节 \n",s_buf.st_size);

}
//   int stat(const char *pathname, struct stat *buf);
//   int fstat(int fd, struct stat *buf);
//   int lstat(const char *pathname, struct stat *buf);
//   lstat不跟踪符号链接
//
// 	struct stat {
//		dev_t	 st_dev;		 /* ID of device containing file */
//		ino_t	 st_ino;		 /* inode number */
//		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 ID (if special file) */
//		off_t	 st_size;		/* total size, in bytes */
//		blksize_t st_blksize;	 /* blocksize for filesystem I/O */
//		blkcnt_t  st_blocks;	  /* number of 512B blocks allocated */
//
//		/* 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
//	};
//

[email protected]:~/linux_c$ gcc main.c  && ./a.out main.c 
文件名:main.c
文件大小:1454字节 
[email protected]:~/linux_c$

access()文件访问函数,测试文件是否存在程序

[email protected]:~/linux_c$ gcc main.c  && ./a.out main.c 
./main.c 存在
[email protected]:~/linux_c$ 
[email protected]:~/linux_c$ 
[email protected]:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
//#include <fcntl.h>

int main(void)
{
	if(access("./main.c",F_OK) < 0)
	{
		perror("open ./haha.txt");
		exit(1);
	}
	printf("./main.c 存在\n");

}
//	int access(const char *pathname, int mode);
//	The mode specifies the accessibility check(s) to be performed, 
//	and is either the value F_OK, or a mask consisting of the bitwise
//	 OR of one or more of R_OK, W_OK,and X_OK. F_OK tests for the
//	 existence of the file.  R_OK, W_OK, and X_OK test whether the
//	 file exists and grants read, write, and execute permissions,  respec‐tively.

//RETURN VALUE:      
//	On success (all requested permissions granted, 
//	or mode is F_OK and the file exists), zero is returned.
//	On error (at least one bit in mode asked for a permission ,
//	that is denied, or mode is F_OK and the file does not exist, 
//	or some other error occurred), -1 is returned, and errno is set appropriately.

[email protected]:~/linux_c$ gcc main.c  && ./a.out main.c 
./main.c 存在
[email protected]:~/linux_c$

黏住位:用户以root权限执行

[email protected]:~$ ll /usr/bin/passwd 
-rwsr-xr-x 1 root root 53K 3月  29 17:25 /usr/bin/passwd*

chmod()函数

[email protected]:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
//#include <fcntl.h>

int main(int argc,char **argv)
{
	if(argc < 3)
	{
		printf("参数不够!\n");
	}
	//需要测试文件是否存在
	//"0222" => 转8进制
	int mode = atoi(argv[2]);
	chmod(argv[1],mode);
}
//需要完善的地方:
//1 字符串转8进制
//2 判断文件是否存在才应该去chmod

[email protected]:~/linux_c$ gcc main.c  && ./a.out file 111
[email protected]:~/linux_c$ ll
总用量 16K
-rwxrwxr-x 1 chunli chunli 8.5K 8月   4 09:59 a.out*
---xr-xrwx 1 chunli chunli    0 8月   4 09:55 file*
-rw-rw-r-- 1 chunli chunli  435 8月   4 09:59 main.c
[email protected]:~/linux_c$ gcc main.c  && ./a.out file 511
[email protected]:~/linux_c$ ll
总用量 16K
-rwxrwxr-x 1 chunli chunli 8.5K 8月   4 10:00 a.out*
-rwxrwxrwx 1 chunli chunli    0 8月   4 09:55 file*
-rw-rw-r-- 1 chunli chunli  435 8月   4 09:59 main.c
[email protected]:~/linux_c$

utime()更新文件时间函数

//    #include <sys/types.h>
//    #include <utime.h>
//
//    int utime(const char *filename, const struct utimbuf *times);
//
//    #include <sys/time.h>
//
//    int utimes(const char *filename, const struct timeval times[2]);

truncate()函数,截断文件

//       #include <unistd.h>
//       #include <sys/types.h>
//
//       int truncate(const char *path, off_t length);
//       int ftruncate(int fd, off_t length);

2.7.1 link

创建一个硬链接

当rm删除文件时,只是删除了目录下的记录项和把inode硬链接计数减1,当硬链接计数

减为0时,才会真正的删除文件。

#include <unistd.h>

int link(const char *oldpath, const char *newpath);

* 硬链接通常要求位于同一文件系统中,POSIX允许夸文件系统

* 符号链接没有文件系统限制

* 通常不允许创建目录的硬链接,某些unix系统下超级用户可以创建目录的硬链

* 创建目录项以及增加硬链接计数应当是一个原子操作

2.7.2 symlink

int symlink(const char *oldpath, const char *newpath)

2.7.3 readlink

读符号链接所指向的文件名字,不读文件内容

ssize_t readlink(const char *path, char *buf, size_t bufsiz)

2.7.4 unlink

int unlink(const char *pathname)

1. 如果是符号链接,删除符号链接

2. 如果是硬链接,硬链接数减1,当减为0时,释放数据块和inode

3. 如果文件硬链接数为0,但有进程已打开该文件,并持有文件描述符,则等该进程关闭该文件时,kernel才真正

去删除该文件

4. 利用该特性创建临时文件,先open或creat创建一个文件,马上unlink此文件

rm 底层也是调用unlink函数

2.8 rename

文件重命名

#include <stdio.h>

int rename(const char *oldpath, const char *newpath);

2.9 chdir

#include <unistd.h>

int chdir(const char *path);

int fchdir(int fd);

改变当前进程的工作目录

2.10 getcwd

获取当前进程的工作目录

#include <unistd.h>

char *getcwd(char *buf, size_t size);

chdir(),getcwd()
       char *getcwd(char *buf, size_t size);//用户自己定义字符数组
       char *getwd(char *buf);		//没有数组大小检查
       char *get_current_dir_name(void);//函数静态数组或者堆空间

获取文件路径

    
[email protected]:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc,char **argv)
{
	char buf [10] = {0};
	chdir("/home");
	getcwd(buf,sizeof(buf));
	printf("%s \n",buf);
}

[email protected]:~/linux_c$ gcc main.c  && ./a.out file 511
/home 
[email protected]:~/linux_c$

pathconf 文件配置信息

#include <unistd.h>

long fpathconf(int fd, int name);

long pathconf(char *path, int name);

[email protected]:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc,char **argv)
{
	printf("%ld\n",fpathconf(STDOUT_FILENO,_PC_NAME_MAX));
	printf("%ld\n",pathconf("./main.c",_PC_NAME_MAX));
	return 0;
}

[email protected]:~/linux_c$ gcc main.c  && ./a.out file 511
255
255
[email protected]:~/linux_c$

opendir()  readdir() 目录遍历

struct dirent
struct stat

[email protected]:~/linux_c$ cat main.c 
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#define MAX_PATH 1024
/* dirwalk: apply fcn to all files in dir */
void dirwalk(char *dir, void (*fcn)(char *))	//遍历目录
{
	char name[MAX_PATH];
	struct dirent *dp;
	DIR *dfd;
	if ((dfd = opendir(dir)) == NULL) 	//如果打开目录失败
	{
		fprintf(stderr, "dirwalk: can‘t open %s\n", dir);
		return;
	}
	while ((dp = readdir(dfd)) != NULL) 	//读取目录内容
	{
		if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
		{
			continue; /* skip self and parent */
		}
		if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name))// 杠与0"/home/chunli\0"
		{
			fprintf(stderr, "dirwalk: name %s %s too long\n",dir, dp->d_name);
		}
		else 
		{
			sprintf(name, "%s/%s", dir, dp->d_name);
			(*fcn)(name);
		}
	}
	closedir(dfd);
}
/* fsize: print the size and name of file "name" */
void fsize(char *name)	//显示文件的大小
{
	struct stat stbuf;
	if (stat(name, &stbuf) == -1) 
	{
		fprintf(stderr, "fsize: can‘t access %s\n", name);
		return;
	}
	if ((stbuf.st_mode & S_IFMT) == S_IFDIR)	//判断是不是目录
	{
		dirwalk(name, fsize);	//如果是目录就递归
	}
	printf("%8ld字节 %s\n", stbuf.st_size, name);
}
int main(int argc, char **argv)
{
	if (argc == 1) /* default: current directory */
	{
		fsize(".");
	}
	else
	{
		while (--argc > 0)	//这样做,可以把程序后面的参数全部遍历
		{
			fsize(*(++argv));
		}
	}
	return 0;
}
[email protected]:~/linux_c$ gcc main.c  && ./a.out ../linux_c/
       0字节 ../linux_c//file
    1504字节 ../linux_c//main.c
   12288字节 ../linux_c//.main.c.swp
    9232字节 ../linux_c//a.out
    4096字节 ../linux_c/
[email protected]:~/linux_c$

dup/dup2

#include <unistd.h>

int dup(int oldfd);

int dup2(int oldfd, int newfd);

dup和dup2都可用来复制一个现存的文件描述符,使两个文件描述符指向同一个file结

构体。如果两个文件描述符指向同一个file结构体,File Status Flag和读写位置只保存一

份在file结构体中,并且file结构体的引用计数是2。如果两次open同一文件得到两个文件

描述符,则每个描述符对应一个不同的file结构体,可以有不同的File Status Flag和读写

位置。请注意区分这两种情况。

[email protected]:~/linux_c$ cat main.c 
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
	int fd, save_fd;
	char msg[] = "This is a test\n";
	fd = open("somefile", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
	if(fd<0) {
		perror("open");
		exit(1);
	}
	printf("fd = %d\n",fd);

	save_fd = dup(STDOUT_FILENO);
	printf("save_fd = %d\n",save_fd);
	dup2(fd, STDOUT_FILENO);	//这个步骤会关闭STDOUT_FILENO, fd就是标准输出了
	printf("第3次 fd = %d\n",fd);
	close(fd);
	write(STDOUT_FILENO, msg, strlen(msg));
	dup2(save_fd, STDOUT_FILENO);
	write(STDOUT_FILENO, msg, strlen(msg));
	close(save_fd);
	return 0;
}

[email protected]:~/linux_c$ gcc main.c  && ./a.out 
fd = 3
save_fd = 4
This is a test
[email protected]:~/linux_c$ cat somefile 
第3次 fd = 3
This is a test
[email protected]:~/linux_c$

2.14 练习

1. 实现ls -l功能,可以解析文件权限位。

2. 实现ls -l功能,可以解析出文件所有者和文件所有组。(偏难)

3. 实现rm删除命令,如

rm file

rm directory

*注意,千万不要在你有代码的目录下做测试,防止删除你的有用文件,友情提示(rmdir/unlink和递归遍历目

录)

4. 从文件里面读出1000个随机数,进行排序,再写到另一文件中。(考虑使用重定向dup/dup2)

时间: 2024-11-03 05:34:23

Linux系统开发 3 文件系统开发 文件/目录的相关文章

《Linux学习并不难》文件系统管理(3):在Linux系统中创建文件系统

18.3  <Linux学习并不难>文件系统管理(3):在Linux系统中创建文件系统 使用mkfs命令可以在分区上创建各种文件系统.mkfs命令本身并不执行建立文件系统的工作,而是去调用相关的程序来执行.这里的文件系统是要指定的,比如xfs.ext4.ext3.vfat或者是msdos等. 命令语法: mkfs [选项] [设备] 命令中各选项的含义如表所示. 选项 选项含义 -t <文件系统类型> 指定文件系统类型 -v 显示详细信息 例:为/dev/sda5磁盘分区创建xfs

在linux系统上建文件系统,建用户,修改用户所属组,重置用户密码

在linux系统上建文件系统,建用户,修改用户所属组,重置用户密码 实验背景:用户及空间 用户名:bosswlb    组别和附属组: bosswlb      主目录:/bosswlb            Shell:bash 空间: 新增    (新增/扩容) 5G   ■解锁  ■密码重置 abcd1234 第一点:建立新的文件系统 我们先来看下系统上现有的文件系统,如下图所示: 下面开始增加一块大小为5G的新盘,使用下面任意一个命令可以扫到新盘: 1.#echo '- - - '> 

linux系统下迁移mysql数据库文件

linux下(这里是centos),mysql安装后,数据库的数据默认存放在/var/lib/mysql目录下,如果该目录下挂载的磁盘空间很少,不够用,需要迁移到其他的目录位置. 方法一: 参照windows下的方法,把/var/lib/mysql移到需要的目录,再修改/etc/my.cnf文件,指定数据目录.这方面的教程网上很多,大家可以去搜索一下. 方法二: 使用linux下的软连接方法,具体操作如下:(以迁移到/home/mysql/目录为例) 先停止mysql: /etc/init.d/

linux系统产生和调试coredump文件

系统配置了coredump后,当程序异常终止时操作系统会在指定的目录下按指定的文件名格式产生一个core文件.core文件是程序内存映像以及相关的调试信息,通过gdb调试coredump文件可以知道导致程序异常终止的原因. 1.系统配置coredump 首先是打开coredump,通过ulimit命令看coredump是否开启: [[email protected] coredump]# ulimit -a core file size (blocks, -c) unlimited data s

Linux基础 linux系统中的批量删除文件与空文件删除的命令介绍

Linux基础教程  linux系统中的批量删除文件与空文件删除的命令介绍 Linux资料下面删除文件或者目录命令rm(remove): Linux培训功能说明:删除文件或目录. 语 法:rm [-dfirv][--help][--version][文件或目录...] 补充说明:执行rm指令可删除文件或目录,如欲删除目录必须加上参数"-r",否则预设仅会删除文件. 参 数: -d或--directory 直接把欲删除的目录的硬连接数据删成0,删除该目录. -f或--force 强制删除

嵌入式 Linux系统编程(一)——文件IO

嵌入式 Linux系统编程(一)--文件IO 一.文件IO概念 linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件IO操作.不带缓存的属于直接调用系统调用(system call)的方式,高效完成文件输入输出.它以文件标识符(整型)作为文件唯一性的判断依据.这种操作不是ASCI标准的,与系统有关,移植有一定的问题.而带缓存的是在不带缓存的基础之上封装了一层,维护了一个输入输出缓冲区,使之能跨OS,成为ASCI标准,称为标准IO库.不带缓存的方式频繁进行用户态 和内核

【转】linux系统下怎么安装.deb文件?

linux系统下怎么安装.deb文件? deb 是 ubuntu .debian 的格式.rpm 是 redhat .fedora .suse 的格式. 他们不通用(虽然可以转换一下). deb是debian发行版的软件包ubuntu是基于debian 发行的 所有可以用 .deb是solaris系统下的安装包后缀名.安装方法如下 cd 到安装包的目录 dpkg -i 安装包名字 如果你使用的是red hat linux,然后运行以下命令安装 cd 到安装包的目录rpm -ivh 安装包名字

linux系统下怎么安装.deb文件

linux系统下怎么安装.deb文件? deb 是 ubuntu .debian 的格式.rpm 是 redhat .fedora .suse 的格式. 他们不通用(虽然可以转换一下). deb是debian发行版的软件包ubuntu是基于debian 发行的 所有可以用 .deb是solaris系统下的安装包后缀名.安装方法如下 cd 到安装包的目录 dpkg -i 安装包名字 如果你使用的是red hat linux,然后运行以下命令安装 cd 到安装包的目录rpm -ivh 安装包名字

df 显示目前在Linux系统上的 文件系统的磁盘使用情况

Linux系统: df命令用于显示目前在Linux系统上的文件系统的磁盘使用情况统计. 应用场景:检查磁盘内存使用状态,便于清理磁盘 语法:df [选项] [file] 中括号代表可选可省略项 显示指定磁盘文件的可用空间.如果没有文件名被指定,则所有当前被挂载的文件系统的可用空间将被显示.默认情况下,磁盘空间将以 1KB 为单位进行显示,除非环境变量 POSIXLY_CORRECT 被指定,那样将以512字节为单位进行显示 常用命令: df -m | grep /LMONAM df -h --t

Linux系统中修改/etc/profile文件的方法

在Linux系统中etc/profile文件一般是不能更改的,想要更改etc/profile文件就要用一些特殊的技巧进行Linux文件修改.本文就来介绍一下Linux系统中修改/etc/profile文件的方法: etc/profile文件是只读的,直接用vi或gedit打开修改后是无法保存的.要修改profile,需要取得root权限,(使用gedit编辑) $sudo gedit /etc/profile 或者 $sudo -s $gedit /etc/profile 这样打开profile