linux(stat-readdir-dup2)04-虚拟地址空间,stat函数,文件,目录,errno说明,dup2和dup

news2024/11/24 11:30:17

01 学习目标

1.掌握stat/lstat函数的使用
2.了解文件属性相关的函数使用
3.了解目录操作相关的函数的使用
4.掌握目录遍历相关函数的使用
5.掌握dup,dup2函数的使用
6.掌握fcntl函数的使用

02 虚拟地址空间

在这里插入图片描述

03 打开最大文件数量

openmax.c

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

int main()
{
	int num = 3;//根据文件描述表,前三位是输入输出
	char filename[128]={0};
	while(1)
	{
		sprintf(filename,"temp_%04d",num++);
		if(open(filename,O_RDONLY|O_CREAT,0666)<0)
		{
			perror("open err");
			break;
		}
	}
	printf("num == %d\n",num);
	return 0;
}

makefile

###  xxx.c --->xxx

SrcFiles=$(wildcard *.c)
TargetFiles=$(patsubst %.c,%,$(SrcFiles))

all:$(TargetFiles)

%:%.c
	gcc -o $@ $^
clean:
rm -f  $(TargetFiles)

输出:num == 1025

ls -l temp.*

04 stat函数

inode节点与目录项:
在这里插入图片描述
vi+n filename 打开文件,直接显示 第n行

获取文件信息
int stat(const char* pathname,struct stat* buf);

struct timespec
{
	-kernel_time_t tv_sec;  /*seconds*/当前时间到1970.1.1. 0:0:0的秒数
	long tv_nsec; /*nanoseconds*/纳秒
};
1s = 1000 ms 毫秒
1ms = 1000 us 微秒
1us = 1000 ns 纳秒
struct stat  
{   
    dev_t       st_dev;     /* ID of device containing file -文件所在设备的ID*/  
    ino_t       st_ino;     /* inode number -inode节点号*/    
    mode_t      st_mode;    /* protection -类型与权限*/    
    nlink_t     st_nlink;   /* number of hard links -链向此文件的连接数(硬连接)*/    
    uid_t       st_uid;     /* user ID of owner -user id*/    
    gid_t       st_gid;     /* group ID of owner - group id*/    
    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 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 status change - */    
};  

在这里插入图片描述
st_mode:
0-2 其他用户权限
3-5 组用户权限
6-8 用户权限
9-11 特殊权限位
12-15 文件类型

stat函数参数
pathname 文件名
struct stat *buf 传出参数,定义 struct stat sb; &sb
返回值:成功返回0,失败返回-1,设置errno

stat.c:

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

int main(int argc,char * argv[])
{
	if(argc!=2)
	{
		printf("./a.out filename\n");
	}
	struct stat sb;
	stat(argv[1],&sb);
	return 0;
}

05 stat命令

stat hello

在这里插入图片描述

06 实现ls -l 命令

需要使用struct passwd *getpwuid(uid_t uid);//获取用户名,需要传入uid,
 struct passwd 
{ 
    char * pw_name; /* Username, POSIX.1 */ 
    char * pw_passwd; /* Password */ 
    __uid_t pw_uid; /* User ID, POSIX.1 */ 
    __gid_t pw_gid; /* Group ID, POSIX.1 */ 
    char * pw_gecos; /* Real Name or Comment field */ 
    char * pw_dir; /* Home directory, POSIX.1 */ 
    char * pw_shell; /* Shell Program, POSIX.1 */ 
}; 
struct group *getgrgid(gid_t gid);//获得组名

获取本地时间
struct tm *localtime(const time_t *timep);
传入参数timep,对应stat函数得到的结构体的秒数(time_t类型)

返回tm结构

struct tm
{
  int tm_sec;                   //分后的秒(0~61)
  int tm_min;                   //小时后的分(0~59)
  int tm_hour;                  //小时(0~23)
  int tm_mday;                  //一个月天数(0~31)
  int tm_mon;                   //一个后的月数(0~11),需要+1
  int tm_year;                  //1900年后的年数 Year - 1900.  
  int tm_wday;                  //星期日开始的天数(0~6)
  int tm_yday;                  //从1月1日开始的时间(0~365)
  int tm_isdst;                 //夏令时标志(大于0说明夏令时有效,等于0说明无效,小于0说明信息不可用)
};
// -rwxrwxr-x 2 itheima itheima 22 5 月 20 10:19 hello
#include<stdio.h>
#include<unistd.h>
#inlude<sys/types.h>
#include<sys/stat.h>
#include<fcnt1.h>
#include<string.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>

int main(int argc,char * argv[])
{
	if(argc!=2)
	{
		printf("./a.out filename\n");
		return -1;
	}
	//调用stat,得到文件属性信息
	struct stat sb;
	stat(argv[1],&sb);
	
	//解析属性信息,st_mode,uid,gid,time
	//st_mode
	char stmode[11]={0};
	memset(stmode,'-',sizeof(stmode));
	if(S_ISREG(sb.stmode)) stmode[0]='-';//普通文件
	if(S_ISDIR(sb.stmode)) stmode[0]='d';
	if(S_ISCHR(sb.stmode)) stmode[0]='c';
	if(S_ISBLK(sb.stmode)) stmode[0]='b';
	if(S_ISFIFO(sb.stmode)) stmode[0]='p';
	if(S_ISLINK(sb.stmode)) stmode[0]='l';
	if(S_ISSOCK(sb.stmode)) stmode[0]='s';
	
	//解析权限
	if(sb.st_mode & S_IRUSR) stmode[1]='r';
	if(sb.st_mode & S_IWUSR) stmode[2]='w;
	if(sb.st_mode & S_IXUSR) stmode[3]='x';
	
	if(sb.st_mode & S_IRGRP) stmode[4]='r';
	if(sb.st_mode & S_IWGRP) stmode[5]='w';
	if(sb.st_mode & S_IXGRPR) stmode[6]='x';

	if(sb.st_mode & S_IROTH) stmode[7]='r';
	if(sb.st_mode & S_IWOTH) stmode[8]='w';
	if(sb.st_mode & S_IXOTH) stmode[9]='x';
	
	//分析 用户名,组名可以通过函数获得 getpwuid,getgrgid
	//时间获取
	struct tm *filename = localtime(&sb.st_atim.tv_sec);
	char timebuf[20]={0};
	sprintf(timebuf,"%d月 %d %02d:%02d",filetm->tm_mon+1,filetm->tm_mday,filetm->tm_hour,filetm->tm_min);
	
	printf("%s %d %s %s %ld %s %s\n",stmode,sb.st_nlink,getpwuid(sb.st_uid)->pw_name,getgrgid(sb.st_gid)->gr_name,sb.st_size,timebuf,argv[1]);
	return 0;
}

通过gdb调试:
p查看结构体信息
p/o 按照8进制显示数据

07 stat与lstat的区别

注意stat与lstat的区别:
stat碰到链接,会追溯到源文件,穿透!!lstat并不会穿透。
通过stat也可以计算文件大小:st_size

08 access,chmod与truncate

access判断文件的权限和是否存在

int access(const char* pathname,int mode);

  • pathname 文件
  • mode 具体权限
    R_OK
    W_OK
    X_OK
    F_OK
  • 返回值:
    如果有权限或者文件存在,对应返回0.

access.c:

#include<stdio.h>
#include<unistd.h>

int main(int argc,char * argv[])
{
	if(argc!=2)
	{
		printf("./a.out filename\n");
		return -1;
	}
	if(access(argv[1],R_OK)==0) printf("%s read ok!\n);
	if(access(argv[1],W_OK)==0) printf("%s write ok!\n);
	if(access(argv[1],X_OK)==0) printf("%s exe ok!\n);
	if(access(argv[1],F_OK)==0) printf("%s file exists!\n);
	return 0;
}

chmod修改文件权限

int chmod(const char *path,mode_t mode);
int fchmod(int fs,mode_t mode);

  • 返回值
    成功返回0,
    失败返回-1,设置errno.

truncate 截断文件

int truncate(const char* path,off_t length);

  • path 文件名
  • length 长度如果大于源文件,直接拓展,如果小于源文件,截断为length长度。
  • 返回值:

09 readlink_unlink

创建硬链接

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

  • oldpath 源文件
  • newpath 硬链接文件

创建软链接

int symlink(const char* target,const char* linkpath);

读取软链接(读取不了硬链接)

ssize_t readlink(const char* pathname,char* buf,size_t bufsize);

  • pathname 连接名
  • buf 缓冲区
  • bufsize 缓冲区大小
  • 返回值:成功返回buf填充的大小,失败返回-1
int main()
{
	char buf[32]={0};
	readlink("hello.soft1",buf,sizeof(buf));
	printf("buf is %s\n",buf);
	
	//unlink("hello.soft1");
	//unlink("hello.hard1");
	unlink("hello");
	return 0;
}

unlink 删除软硬链接

int unlink(const char* pathname);

  • pathname 对应的链接名字,文件也可以

unlink.c:

#include<unistd.h>
#include<stdlib.h>
#include<fcnt1.h>
#include<string.h>
#include<sys/types.h>

int main(int argc,char *argv[])
{
	int fd = open("world",O_WRONLY|O_CREAT,0666);
	unlink("world");
	
	int ret = write(fd,"hello",5);
	if(ret>0)
	{
		printf("write ok!%d\n",ret);
	}
	if(ret<0)
	{
		perror("write err");
	}
	close(fd);
	return 0;
}

输出:writer ok!5,但没有hello文档
unlink使用:发现文档在使用时,并不会删除文档,结束后会删除,所有有上述输出效果。视频软件就是使用此技术:先缓冲视频,当看完后,会将缓存的视频删除。

10 chown与rename

chown 改变用户和组

int chown(const  *pathname,uid_t owner,gid_t group)
  • pathname 文件名
  • owner 用户ID,/etc/group
  • group 组ID,/etc/group

rename 重命名文件

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

  • oldpath 旧文件
  • newpath 新文件

11 chdir_getcwd切换目录和获得工作路径

目录相关函数
getcwd 获得当前工作路径

char *getcwd(char *buf,size_t size)

  • buf 传出参数,路径
  • size 缓冲区大小
  • 返回值:
    成功返回 路径的指针
    失败返回NULL

chdir 改变工作路径-注意属于进程独有

int chdir(const char* path)

  • path 对应的目标工作路径
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcnt1.h>

int main()
{
	//先切换工作目录
	
	//留下点痕迹
	int fd = open("temp",O_WRONLY|O_CREAT,0666);
	write(fd,"daociyiyou",10);
	close(fd);
	//显示当前工作目录
	char buf[256];
	getcwd(buf,sizeof(buf));
	
	printf("buf is [%s]\n",buf);
	return 0;
}

12 mkdir创建目录

mkdir 创建目录

int mkdir(const char *pathname,mode_t mode)

  • pathname 路径
  • mode mode& ~umask&0777注意权限,如果目录没有可执行权限,不可进入。
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>

int main(int argc,char * argv[])
{
	if(argc!=2)
	{
		printf("./a.out filename\n");
		return -1;
	}
	mkdir(argv[1],0777);
	return 0;
}

13 读目录相关函数介绍

统计一下指定目录下普通文件的个数,要求子目录递归
itheima@ubantu:~/linux/code/file_dir$find ./ -type f |wc -l

opendir 打开目录

DIR * opendir(const char* name)

  • name 打开的目录
  • 返回值,返回DIR* 的指针,指向目录项的信息

readdir 读目录

struct dirent *readdir(DIR * dirp);

  • dirp 传入参数,opendir返回的指针
  • 返回值:
    NULL代表读到末尾或者有错误
    读到目录项的内容

closedir 关闭目录

int closedir(DIR * dirp)

  • dirp opendir得到的DIR指针

rewinddir 把目录指针恢复到起始位置

void rewinddir(DIR * dirp)

telldir 获取目录读写位置

long telldir(DIR *dirp)

  • 返回值:
    成功返回 当前在目录中的位置
    失败返回-1,设置errno

seekdir 修改目录读写位置

void seekdir(DIR *dirp,long loc)

14 递归子目录统计普通文件个数

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

int count = 0;//定义一个全局的计数

int DirCount(char * dirname)
{
	printf("%s\n",dirname);
	//打开目录
	struct DIR *dirp=opendir(dirname);
	if(dirp == NULL)
	{
		perror("opendir err");
		return -1;
	}
	//循环读目录,如果是普通文件,count++,如果是目录,继续调用DirCount
	struct dirent *dentp = NULL;
	while((dentp = readdir(drip))!=NULL)//如果为NULL,代表读到目录末尾
	{
		//printf(“dirname:%s,dtype:%d\n”,dentp->d_name,dentp->d_type);
		if(dentp->d_type ==DT_DIR)//如果是目录
		{
			if(strcmp(".",dentp->d_name)==0||strcmp("..",dentp->d_name)==0)
			{
				continue;//如果是.或者..,直接跳过
			}
			//注意进程的工作路径,不能直接打开子目录
			//使用dirname拼接下一级子目录
			char newdirname[256]={0};
			sprintf(newdirname,"%s/%s",dirname,dentp->d_name);
		}
		if(dentp->d_type == DT_REG)
		{
			//普通文件,开始计数
			count++;
			printf("dname:%s\n",dentp->d_name);
	}
	//关闭目录
	closedir(drip);
	reuturn 0;
}

int main(int argc,char * argv[])
{
	if(argc!=2)
	{
		printf("./a.out filename\n");
		return -1;
	}
	DirCount(argv[1]);
	return 0;
}

此程序输出比命令的多,因为此程序也会生成文件。

15 errno说明

errno 输出函数

char *strerror(int errnum);

16 dup2和dup

dup2 重定向

int dup2(int oldfd,int newfd);

  • 关闭newfd对应的文件描述符
  • 将newfd重新指向为oldfd对应的文件

dup 复制文件描述符

int dup(int oldfd)

  • 新返回一个文件描述符指向oldfd对应的文件

实现突发奇想的功能,在代码中执行2次print(“hello world\n”);一次输出到hello文件中,后一次输出到屏幕上。

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

int main()
{
	//先备份现场
	int outfd = dup(1);
	//先做重定向
	int fd = open("world",O_WRONLY|O_CREAT,0666);
	dup2(fd,1);//将标准输出重定向到fd对应的文件
	printf("hello worlf\n");
	//需要来一次刷新下
	fflush(stdout);
	
	//需要恢复,重新对应 标准输出
	dup2(outfd,1);
	printf("hello worlf\n");
	close(fd);
	return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/489544.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redo log详解

WAL&#xff08;Write-Ahead Logging&#xff09;机制 WAL 的全称是 Write-Ahead Logging&#xff0c;中文称预写式日志(日志先行)&#xff0c;是一种数据安全写入机制。就是先写日志&#xff0c;然后再写入磁盘&#xff0c;这样既能提高性能又可以保证数据的安全性。Mysql中的…

华为MPLS跨域C2方式RR场景(数据不经过RR)实验配置

目录 配置BGP邻居的建立 配置MPLS LDP 配置RR之间的MP-BGP邻居 配置通过ASBR学习PE路由并为PE分配标签&#xff08;实现Vpnv4路由传递和数据传输&#xff09; 根据图配置接口的IP地址和IGP协议 配置BGP邻居的建立 PE1和RR1建立MP-IBGP邻居&#xff08;RR1传给PE1的Vpnv4路…

进程/线程 状态模型详解

前言&#xff1a;最近操作系统复习到线程的状态模型&#xff08;也可以说进程的状态模型&#xff0c;本文直接用线程来说&#xff09;时候&#xff0c;网上查阅资料&#xff0c;发现很多文章都说的很不一样&#xff0c;有五状态模型、六状态模型、七状态模型.......虽然都是对的…

【1024杯】web

文章目录 1024_fastapi信息收集SSTI 1024_柏拉图信息收集phar反序列化 1024_WEB签到1024_图片代理信息收集gopherus|fastcgi 1024_hello_world信息收集ssti盲注 1024_fastapi 信息收集 FastAPI 是一个高性能 Web 框架&#xff0c;用于构建 API。 主要特性&#xff1a; 快速&am…

【头歌】完整汇编语言程序设计

摘自头歌实训​​​​​​ 目录 相关知识 1.1 RISC-V 汇编语言程序基本结构 1.2 RISC-V 汇编语言程序主要元素 1.2.1 汇编指令 1.2.2 标签 1.2.3 汇编指示语句 1.3 RISC-V 汇编语言程序示例 相关知识 RISC-V 操作数类型、基本调用约定等已在前序关卡中介绍&#xff0c;…

云渲染是您3D项目的最佳选择吗?

市面上很多优秀的大型动画电影&#xff0c;一般都是由实力较大的视觉特效团队制作的&#xff0c;而且大部分使用的是基于云的渲染服务来进行最终渲染。像《哪吒之魔童降世》这样 IMAX 3D 首部国产动画电影、并且刷新了中国动画电影票房纪录的作品&#xff0c;就是现代3D动画提供…

ChatGPT做PPT方案,10组提示词方案!

今天我们要搞定的PPT内容是&#xff1a; 活动类型&#xff1a;节日活动、会员活动、新品活动分析类型&#xff1a;用户分析、新品立项、项目汇报内容类型&#xff1a;内容规划、品牌策划 用到的工具&#xff1a; mindshow 邀请码 6509097ChatGPT传送门&#xff08;免费使用…

《Linux0.11源码解读》理解(二) 加载setup、加载system

现在CPU开始执行bootsect&#xff0c;它的作用是把第二部分、第三部分程序陆续加载到内存中。把放到合理的内存位置需要先对内存进行规划。 根据上一节&#xff0c;boostsect当前所在内存位置是0x07c0&#xff0c;大小为512byte&#xff0c;现在要将其挪动到内存的0x9000&…

无代码时代来了,程序员会失业吗?不,程序员又不够用了!

有人问我无代码时代来了&#xff0c;程序员会失业吗&#xff1f;太难了&#xff0c;秃了头就算了&#xff0c;连工作也保不住了&#xff1f; 先说观点&#xff1a;并不会 因为&#xff0c;无代码不是真正意义上的无代码。 无代码开发的使用对象是编程小白&#xff08;我猿是…

Redis的命令以及数据类型

1.Redis的通用命令 KEYS&#xff1a;查看符合模板的所有key&#xff0c;不建议在生产环境设备上使用 DEL&#xff1a;删除一个指定的key EXISTS&#xff1a;判断key是否存在 TTL&#xff1a;查看一个KEY的剩余有效期 2.String类型 String类型&#xff0c;也就是字符串类型…

【Halcon】 Halcon 22.11 安装详细教程

文章目录 1安装2 获取许可证 license2.1 license下载2.2 激活 license放置在相应文件夹下 3 DLT 安装 1安装 1.解压安装包 2.打开运行 exe 程序 跳转至页面 点击“可获得的”&#xff0c;并安装 选择&#xff1a; AVAILABLE ->INSTALL 可获得的 ->安装 5. 等待安装 6…

jQuery -- 常用API(下)

4. jQuery属性操作 4.1 设置或获取元素固有属性值prop() 所谓元素固有属性就是元素本身自带的属性&#xff0c;比如 元素里面的 href &#xff0c;比如 元素里面的 type。 获取属性语法&#xff1a;prop(属性)设置属性语法&#xff1a;prop(属性, 属性值) 4.2 设置或获取元…

掌握黑客技术:从Kali渗透测试开始

前言 Kali Linux是一种流行的渗透测试和网络安全工具&#xff0c;广泛用于测试和评估网络系统和应用程序的安全性。下面是一个简单的Kali Linux使用教程&#xff08;Kali使用教程中需要学习的知识点&#xff09;&#xff0c;旨在帮助初学者了解如何使用Kali Linux进行渗透测试…

【计算机网络】网络分层结构

应用层 软件 传输层 TCP UDP协议 网络层 实现源主机到目标主机的传输 IP协议 可能会丢失&#xff0c;可能失序、可能错误 工作设备&#xff1a;路由器、防火墙 链路层 相邻两点的数据传输以帧为单位的数据。 工作设备&#xff1a;交换机 物理层 光信号 电信号 网络边…

15.JVM8为什么要增加元空间

JVM从永久代至元空间内存结构变化图 变化后的java8图 变化之前java7以及之前各代的图 看出变化了吗&#xff1f;堆和方法区连在了一起&#xff0c;但这并不能说堆和方法区是一起的&#xff0c;它们在逻辑上依旧是分开的。但在物理上来说&#xff0c;它们又是连续的一块内存。…

面了一个4年经验的测试工程师,自动化都不会也要15k,我也是醉了····

在深圳这家金融公司也待了几年&#xff0c;被别人面试过也面试过别人&#xff0c;大大小小的事情也见识不少&#xff0c;今天又是团面的一天&#xff0c; 一百多个人都聚集在一起&#xff0c;因为公司最近在谈项目出来面试就2个人&#xff0c;无奈又被叫到面试房间。 整个过程…

mxf文件格式详解

MXF是英文Material eXchange Format&#xff08;素材交换格式&#xff09;的缩语。MXF是SMPTE&#xff08;美国电影与电视工程师学会&#xff09;组织定义的一种专业音视频媒体文件格式。MXF主要应用于影视行业媒体制作、编辑、发行和存储等环节。SMPTE381M&#xff08;把MPEG格…

如何在 Linux 中使用 GPG 加密和解密文件?

什么是 GPG&#xff1f; GPG&#xff08;GNU Privacy Guard&#xff09;是一种免费的开源加密软件&#xff0c;用于保护计算机数据的机密性和完整性。 它使用非对称加密算法&#xff0c;也称为公钥加密算法&#xff0c;其中数据被加密和解密时使用不同的密钥。每个用户都有一个…

【C++】类与对象(2)

【C】类与对象&#xff08;2&#xff09; 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.5.4 本篇博客有关构造函数、析构函数、拷贝构造的知识&#xff0c;由于本篇博客可能比较详细&#xff0c;还剩一些内容没介绍&#xff0c;所以我将剩余的知识放在下一篇博客。 目…

探究Spring中Bean的线程安全性问题

前言 今天同事笑嘻嘻的凑过来&#xff0c;问了我一个问题&#xff1a;spring中的bean是线程安全的吗&#xff1f;。我内心一想肯定是安全的&#xff0c;毕竟这样多项目在用。但是转念一想&#xff0c;他那贱兮兮的表情&#xff0c;多半是在给我挖坑。于是我自信的回答他&#x…