Linux操作系统学习第三篇博客

本文深入讲解了Linux系统下的文件操作,包括open、read、write、lseek、stat等函数的使用方法,以及如何通过rename、chdir、mkdir等函数进行目录操作。同时,介绍了文件权限检查、文件删除和临时文件的创建,还探讨了目录遍历和文件数量统计的递归实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、虚拟地址空间

   查看文件格式:file + 文件名

2、open函数

(1)open函数的形式

    <1> int open(const char * pathname , int flags , mode_t mode);
        
        相关注释:
        ① const char * pathname:代表文件名
        ② int flags:代表执行命令(例如:只读、只写、读写等)
        ③ mode_t mode:代表设置文件权限
      
    <2> 相关打开文件命令
        ① O_RDONLY:只读
        ② O_WRONLY:只写
        ③ O_RDWR:即读又写
        ④ O_CREAT:自动创建指定新的文件
        ⑤ O_TRUNC:如果文件存在并且以可写方式打开时,使原文件内容清空为0
        ⑥ O_APPEND:以追加的方式打开文件
        ⑦ O_EXCL:和O_CREAT一起用,判断此文件是否存在,如果不存在,则输出错误信息并且创建该文件
    
    <3> 相关头文件
        ① #include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>

(2)有关代码

**//打开文件** 

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcnl.h>
#include <unistd.h>

int main()
{
	int fd;
	fd = open("hello.c",O_RDWR);
	if(fd==-1)
	{
		perror("open file error");
		exit(1);	
	}
	int ret;
	ret = close(fd);
	if(ret==-1)
	{
		perror("close file error");
		exit(1);	
	}
	return 0;		
} 



**//创建文件**

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcnl.h>
#include <unistd.h>

int main()
{
	int fd;
	fd = open("hello.c",O_CREAT | O_RDWR,0777);
	if(fd==-1)
	{
		perror("open file error");
		exit(1);	
	}
	int ret;
	ret = close(fd);
	if(ret==-1)
	{
		perror("close file error");
		exit(1);	
	}
	return 0;		
}  



**//判断文件是否存在,若不存在则创建文件并且输出错误信息**

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcnl.h>
#include <unistd.h>

int main()
{
	int fd;
	fd = open("hello.c",O_CREAT | O_EXCL | O_RDWR,0777);
	if(fd==-1)
	{
		perror("open file error");
		exit(1);	
	}
	int ret;
	ret = close(fd);
	if(ret==-1)
	{
		perror("close file error");
		exit(1);	
	}
	return 0;		
} 



**//清除指定文件的内容**

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcnl.h>
#include <unistd.h>

int main()
{
	int fd;
	fd = open("hello.c",O_TRUNC);
	if(fd==-1)
	{
		perror("open file error");
		exit(1);	
	}
	int ret;
	ret = close(fd);
	if(ret==-1)
	{
		perror("close file error");
		exit(1);	
	}
	return 0;		
}    

3、read和write函数

(1)read函数的返回值

1|   返回值为-1:说明文件读取失败

2|   返回值为0:说明文件已经读完了

3|   返回值为一个大于0的数:说明返回值为读取的字节数

(2)有关代码

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

int main()
{
	//打开一个新的文件 
	int fd;
	fd = open("hello.c",O_RDONLY);
	if(fd == -1)
	{
		perror("open error");
		exit(1);	
	}
	//创建一个新的文件 
	int fd1;
	fd1 = open("creat.c",O_CREAT | O_WRONLY,0777);
	
	//读取文件 
	char a[2048]={0};
	int count;
	count = read(fd,a,sizeof(a));
	if(count == -1)
	{
		perror("read error");
		exit(1); 
	}
	while(count!=0)
	{
		int ret;
		//将读出的数据写入创建的文件中 
		ret = write(fd1,a,count);
		printf("write bytes %d\n",ret);
		//继续读取数据 
		count = read(fd,a,sizeof(a));	
	}
	//关闭相关文件 
	close(fd);
	close(fd1);	
} 

4、lseek函数

(1)函数结构

   off_t lseek(int fd , off_t offset , int whence)

(2)有关参数

1|   SEEK_SET:将指针指向文件头之后再增加offset个位移量

2|   SEEK_CUR:以目前的光标位置往后增加offset个位移量

3|   SEEK_END:将光标指向文件尾部后再增加offset个位移量

(3)相关代码

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

int main()
{
	int fd;
	fd = open("aa",O_RDWR);
	if(fd == -1)
	{
		perror("open error");
		exit(1);	
	}
	
	//获取文件长度
	int ret;
	ret = lseek(fd,0,SEEK_END);
	printf("The file length is :%d\n",ret);
	
	//文件拓展
	ret = lseek(fd,2000,SEEK_END);
	printf("return value : %d\n",ret);
	
	//实现文件拓展,需要最后进行一次写操作
	write(fd,"a",1);
	close(fd);
	return 0;  
} 

5、stat函数

(1)函数形式

    int stat(const char * path,struct stat * buf);

(2)包含的struct结构体

1|   dev_t          st_dev      //文件的编号

2|   ino_t          st_ino      //节点

3|   mode_t         st_mode     //文件类型和存储权限

4|   nlink_t        st_nlink    //连接到该文件的硬链接数目,刚刚建立的文件值为1

5|   uid_t          st_uid      //用户ID

6|   gid_t          st_gid      //组ID

7|   dev_t          st_rdev     //(设备类型)如果此文件为设备文件,则为其设备编号

8|   off_t          st_size     //文件字节数(文件大小)

9|   blksize_t      st_blksize  //块的大小(文件系统的I/O缓冲区的大小)

10|  blkcnt_t       st_blocks   //块数

11|  time_t         st_atime    //最后一次访问时间

12|  time_t         st_mtime    //最后一次修改时间

13|  time_t         st_ctime    //最后一次改变世界(指的是属性)

(3)有关代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>

int main(int argc,char* argv[])
{
	if(argc<2)
	{
		printf("./a.out filename\n");
		exit(1);	
	}
	
	struct stat st;
	int ret;
	ret = stat(argv[1],&st);
	if(ret==-1)
	{
		perror("stat");	
	}
	
	//存储文件类型和访问权限
	char perms[11] = {0};
	//判断文件类型
	switch(st.st_mode & S_IFMT)
	{
		case S_IFLNK:
		    perms[0] = '1';
			break;
		case S_IFDIR:
		    perms[0] = 'd';
			break;
		case S_IFREG:
		    perms[0] = '-';
			break;
		case S_IFBLK:
		    perms[0] = 'b';
			break;	
		case S_IFCHR:
			perms[0] = 'c';
			break;
		case S_IFSOCK:
			perms[0] = 's';
			break;
	}
	
	//判断文件的访问权限
	//文件所有者
	perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';
	perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-';
	perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-';
	//文件所属组
	perms[4] = (st.st_mode & S_IRUSR) ? 'r' : '-';
	perms[5] = (st.st_mode & S_IWUSR) ? 'w' : '-';
	perms[6] = (st.st_mode & S_IXUSR) ? 'x' : '-';
	//其他人
	perms[7] = (st.st_mode & S_IRUSR) ? 'r' : '-';
	perms[8] = (st.st_mode & S_IWUSR) ? 'w' : '-';
	perms[9] = (st.st_mode & S_IXUSR) ? 'x' : '-';
	
	//硬链接计数
	int linkNum = st.st_nlink;
	//文件所有者
	char* fileUser = getpwuid(st.st_uid) ->pw_name;
	//文件所属组
	char* fileGrp = getgrgid(st.st_gid) ->gr_name;
	//文件大小
	int fileSize = (int)st.st_size;
	//修改时间
	char* time = ctime(&st.st_mtime);
	char mtime[512] = {0};
	strncpy(mtime,time,strlen(time)-1);
	
	char buf[1024];
	sprintf(buf,"%s %d %s %s %d %s %s",perms,linkNum,fileUser,fileGrp,fileSize,mtime,argv[1]);
	printf("%s\n",buf);
	return 0; 
} 

6、stat和lstat函数

(1)区别

1|  stat:穿透函数(追踪函数)        —————— 对于软链接   (例如:软链接的大小和原文件大小显示相同)

2|  lstat:不穿透函数(不追踪函数)   —————— 对于软链接    (例如:软链接的大小和原文件大小显示不相同)

(2)用法的代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc,char* argv[])
{
	if(argc < 2)
	{
		printf("./a.out filename\n");	
	}
	struct stat st;
	int ret;
	ret = lstat(argv[1],&st);
	//ret = stat(argv[1],&st);
	if(ret == -1)
	{
		perror("stat error");
		exit(1);
	}
	
	//获取文件大小
	int size;
	size = (int)st.st_size;
	printf("file size is:%d\n",size); 
} 

7、一些系统函数介绍

1|  int access(const char *pathname,int mode)
    参数:pathname(文件名)
    mode(权限类别):
    ① R_OK:是否有读权限
    ② W_OK:是否有写权限
    ③ X_OK:是否有执行权限
    ④ F_OK:测试的该文件是否存在

2|  int chmod(const char *path,mode_t mode)

3|  int chown(const char *path,uid_t owner,gid_t group)

8、unlink创建临时文件

(1)函数形式

    int unlink(const char* pathname);

(2)函数说明

1|  unlink可以从文件系统里面删除一个指定文件

2|  如果返回值为-1,说明失败       如果返回值为0,说明成功

3|  在执行unlink函数之后依然可以读到文件中的内容,但是在整个程序执行完毕后文件会被删除

(3)有关代码

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

int main()
{
	int fd;
	fd = open("tempfile",O_CREAT | O_RDWR,0664);
	if(fd == -1)
	{
		perror("open error");
		exit(1);	
	}
	
	//删除临时文件 
	int ret;
	ret = unlink("tempfile");
	
	//写文件 
	write(fd,"hello\n",6);
	
	//重置文件指针
	lseek(fd,0,SEEK_SET);
	
	 
	//读文件
	char buf[100] = {0};
	int p;
	p = read(fd,buf,sizeof(buf));
	
	//将读到的文件内容,输出到屏幕上
	write(1,buf,p);
	
	//关闭文件
	close(fd);
	return 0; 
} 

9、目录操作函数

(1)rename函数

1|  作用:文件重命名

2|  函数原型:int rename(const char *oldpath , const char *newpath);

(2)chdir函数

1|  作用:修改当前进程的路径

2|  函数原型:int chdir(const char *path);

(3)getcwd函数

1|  作用:获取当前进程工作的目录

2|  函数原型:char *getcwd(char *buf , size_t size);

(4)mkdir函数

1|  作用:创建目录

2|  注意点:创建的目录需要有执行权限,否则无法进入该目录

3|  函数原型:int mkdir(const char *pathname , mode_t mode);

(5)rmdir函数

1|  作用:删除一个空目录

2|  函数原型:int rmdir(const char *pathname);

10、opendir函数、readdir函数和closedir函数

(1)opendir函数

1|  作用:打开一个目录

2|  函数原型:DIR *opendir(const char *name);

3|  返回值:
    <1> DIR结构指针,该结构是一个内部结构,保存所打开的目录信息,作用类似于FILE结构
    <2> 函数出错返回NULL

(2)readdir函数

1|  作用:读目录

2|  函数原型:struct dirent *readdir(DIR *dirp);

3|  返回值:
    <1> 返回一条记录项
    <2> struct dirent
        {
             ino_t_d ino;                            //此目录进入点的inode(节点)
             ff_t  d_off;                            //目录文件开头到目录进入点的位移
             signed short int d_reclen;              //d_name的长度,不包含NULL字符
             unsigned char d_type;                   //d_name所指的文件类型
             har d_name[256];                        //文件名
        };
     
4|  d_type(文件类型):
    DT_BLK:块设备                        DT_CHR:字符设备                     DT_DIR:目录
    DT_LNK:软连接                        DT_FIFO:管道                        DT_REG:普通文件
    DT_SOCK:套接字                       DT_UNKNOWN:未知   

11、递归实现读目录获取文件个数

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>

int getfilenum(char* root)
{
	//打开目录
	DIR* dir = NULL;
	dir = opendir(root);
	if(dir == NULL)
	{
		perror("opendir error");
		exit(1);	
	}
	
	//遍历当前打开的目录 
	struct dirent* ptr = NULL;
	char path[2048] = {0};
	int total = 0;
	while(ptr = readdir(dir) != NULL)
	{
		//排除掉 . 和 ..
		if(strcmp(ptr->d_name,".")==0||strcmp(ptr->d_name,"..")==0)
		{
			continue;	
		}
		
		//如果是目录
		if(ptr->d_type == DT_DIR)
		{
			//递归读目录
			sprintf(path,"%s/%s",root,ptr->d_name);
			total += getfilenum(path);	
		}
		//如果是普通文件
		if(ptr->d_type == DT_REG)
		{
			total++;	
		}	
	} 
}

int main(int argc,char* argv[])
{
	if(argc < 2)
	{
		printf("./a.out dir\n");
		exit(1);
	}
	
	int total = getfilenum(argv[1]);
	printf("%s has file numbers %d\n",argv[1],total);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值