Linux_C 文件系统

二.文件系统

目录和文件

获取文件属性:

stat:通过文件路径获取属性,面对符号链接文件时获取的是所指向的目标文件

fstat:通过fd获取文件属性

lstat:面对符号链接文件时获取的是符号链接文件的属性

// stat(); -> 获取文件属性
int stat(const char *path,struct stat *buf);
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 file system I/O */ //包含该文件的磁盘块的大小   
    blkcnt_t  st_blocks;  /* number of 512B 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 */ //最后一次改变该文件状态的时间   
};

空洞文件:

// lseek(fd,5LL*1024*1024-1,SEEK_SET); 开辟了一个5G大小的空洞文件,虽然st_size是5G,但是其在磁盘中所占的内存块(st_blocks)却很小

文件属性:

st_mode 是一个16位的位图,用于表示文件类型,文件访问权限,以及特殊权文件访问权限

umask命令:

作用:防止产生权限过松的文件

所有的文件的文件权限都满足:0666 & umask

mode_t umask(mode_t umask);

文件权限的更改/管理:

chmod命令 直接更改文件权限

int chmod(const char *path,mode_t mode);
int fchmod(int fd,mode_t mode);
// 参数:指定文件,修改后的权限

粘住位:t位

​ 功能:把某一个命令的使用痕迹保留,为下一次装载该模块的速度更快

文件系统:FAT,UFS

​ 文件或数据的存储和管理

FAT文件系统:静态存储的单链表

​ 一式俩份,非复制内容,是记录操作

​ 问题:1.如果一份FAT表出现了问题,如何判断哪一份表是正确的

​ 2.只能单走向,查询困难

​ 3.承载的文件数量限制

​ 优点:轻量化,小U盘

UFS文件系统:磁盘分区

​ 分区下有若干块组

​ 块组:描述信息+inode位图+数据块位图+inode节点(结构体数组)+数据块(结构体数组)

​ inode节点:stat,亚数据,隐藏内容,数据块指针组(15个),前12个指针:直接数据块指针,13:一级间接块指针(直接数据块指针数量:大小/指针大小)14:二级间接块指针(直接数据块指针数量:大小/指针大小)15:三级间接块指针(直接数据块指针数量:大小/指针大小)

​ 缺陷:不擅于管理小文件

​ inode位图:0/1确实inode是否使用,确定inode是否使用,确定数据块的使用

​ 文件名:在目录文件中

硬链接,符号链接:

硬链接=目录项:俩个指针指向同一块内存区域

​ 建立硬链接有限制,不能给分区建立(inode的重复问题),不能目录建立

符号链接:类windows的快捷方式,原文件和符号链接文件不是一个文件

​ 优点:可以跨分区建立,可以给目录建立

int link(const char *oldpath,const char *newpath);
// 封装出ln命令
int unlink(const char *pathname);
// 在磁盘上删除链接的目标文件,是否彻底删除文件不得而知
// 用途:匿名文件
// remove(); -> rm命令
// rename(); -> mv命令

utime:可以更改文件的最后读取时间和最后修改时间

目录的创建和销毁:

// mkdir -> 创建
// rmkdir -> 销毁

更改当前工作路径:

cd:chdir() 封装 会突破假 / 技术

假 / 技术:chroot

long getcwd(char *buf,unsigned int bufsize);
// 封装出pwd命令

分析目录/读取目录内容:

// glob(); -> 分析目录
int glob(const char *restrict pattern, int flags,
                int (*errfunc)(const char *epath, int eerrno),
                glob_t *restrict pglob);
// 参数:模式,特殊要求,指向函数的指针(函数:获取出错路径),存放解析出的pattern
// globfree() -> 释放出由于glob()申请的空间 
void globfree(glob_t *pglob);
// opendir(); -> 通过文件名打开一个流
DIR *opendir(const char *name);
// 返回的目录流指针指在堆中的内存
// fopendir(); -> 通过fd打开一个流
DIR *fopendir(int fd);
// closedir(); -> 关闭一个流
int closedir(DIR *dirp);
// readdir(); -> 读取一个流
struct dirent *readdir(DIR *dirp);
// rewinddir(); -> 参考rewind
void rewinddir(DIR *dirp);
// seekdir(); -> 参考seek
void seekdir(DIR *dirp, long loc);  
// telldir(); -> 参考tell
long telldir(DIR *dirp);
struct dirent
{
  long d_ino; /* inode number 索引节点号 */
    off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
    unsigned short d_reclen; /* length of this d_name 文件名长 */
    unsigned char d_type; /* the type of d_name 文件类型 */
    char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}

最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?

首先,我们使用opendir函数打开目录a,返回指向目录a的DIR结构体c。

接着,我们调用readdir©函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。

然后,我们遍历d,调用stat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。

总体就是这样一种逐步细化的过程,在这一过程中,三种结构体扮演着不同的角色。

dir c =  opendir(a)
dirent d readdir(c)
stat e
stat(d->name,&e)

通过上述四步即可在stat结构体e中得到a目录下的b文件的信息
系统的数据文件和信息

/etc/passwd

// getpwnam(); -> 通过文件名获取文件信息
struct passwd *getpwnam(const char *name);
// getpwuid(); -> 通过uid获取文件信息
struct passwd *getpwuid(uid_t uid);
// struct passwd
// {
//     char *pw_name;   /* username */
//     char *pw_passwd; /* user password */
//     uid_t pw_uid;    /* user ID */
//     gid_t pw_gid;    /* group ID */
//     char *pw_gecos;  /* user information */
//     char *pw_dir;    /* home directory */
//     char *pw_shell;  /* shell program */
// };

/etc/group

// getgrgid(); -> 通过gid获取组信息
struct group *getgrgid(gid_t gid);
// getgrgrnam(); -> 通过文件名获取组信息
struct group *getgrnam(const char *name);
// struct group
// {
//     char *gr_name;   /* group name */
//     char *gr_passwd; /* group password */
//     gid_t gr_gid;    /* group ID */
//     char **gr_mem;   /* NULL-terminated array of pointers
//                       to names of group members */
// };

/etc/shadow

密码加密原理:

hash(哈希) 不是加密,是混淆,不可逆

​ 如原串相同,所得串也相同,防备管理员监守自盗

加密 — 解密

加密:安全?no,逃不过穷举

​ 安全:攻击成本大于收益

​ 口令的随机校验 防止脚本攻击

// getspnam(); -> 加密密码文件工具函数
struct spwd *getspnam(char *name);
// struct spwd
// {
//     char *sp_namp;             /* user login name */
//     char *sp_pwdp;             /* encrypted password */
//     long int sp_lstchg;        /* last password change */
//     long int sp_min;           /* days until change allowed. */
//     long int sp_max;           /* days before change required */
//     long int sp_warn;          /* days warning for expiration */
//     long int sp_inact;         /* days before account inactive */
//     long int sp_expire;        /* date when account expires */
//    unsigned long int sp_flag; /* reserved for future use */
// };
// crypt(); -> 加密函数
char *crypt(const char *phrase, const char *setting);
// 参数:原串,杂志串,加密方式:默认MD5

时间戳:time_t char * struct tm

// time(); -> 以秒为单位获取时间
time_t time(time_t t);
//用法:
time_t stamp;
time(&stamp);
stamp = time(NULL);
// gmtime(); 
struct tm *gmtime(const time_t *timep);
// localtime();
struct tm *localtime(const time_t *timep); 
/*
gmtime():将time函数得到的秒数转换成一个UTC时间的结构体struct tm,通过此函数gmtime()是0时区,把UTC时间转换成北京时间的话,需要在年数上加1900,月份上加1,小时数加上8。
localtime():得到本地时间,该函数同gmtime函数唯一区别是,在转换小时数不需要加上8了。localtime是将时区考虑在内了,转出的当前时区的时间。但是注意,有些嵌入式设备上被裁减过的系统,时区没有被设置好,导致二者转出来的时间都是0时区的。
*/
// mktime(); -> struct tm 转换为 time_t 可能会改变struct的内容即判断合法性,若合法不修改,若不合法调整为合法
time_t mktime(struct tm *tm);
// strftime(); -> 格式化时间和日期
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr);
// struct tm {
//    int tm_sec;         /* 秒,范围从 0 到 59        */
//    int tm_min;         /* 分,范围从 0 到 59        */
//    int tm_hour;        /* 小时,范围从 0 到 23        */
//    int tm_mday;        /* 一月中的第几天,范围从 1 到 31    */
//    int tm_mon;         /* 月,范围从 0 到 11        */
//    int tm_year;        /* 自 1900 年起的年数        */
//    int tm_wday;        /* 一周中的第几天,范围从 0 到 6    */
//    int tm_yday;        /* 一年中的第几天,范围从 0 到 365    */
//    int tm_isdst;       /* 夏令时                */
// };
进程环境

main函数:

void main(int argc char *argv[]);

进程的终止情况:

正常终止:从main函数返回

​ 调用:exit

​ 调用 :_exit 或者 _Exit

​ 最后一个线程从其启动例程返回

​ 最后一个线程调用:pthread_exit

异常终止:调用:abork

​ 接到一个信号并终止

​ 最后一个线程对其取消请求作出响应

补充:

// atexit(); -> 钩子函数
int atexit(void (*function)(void));
// 在程序正常终止时,程序会调用钩子函数

exit 依赖于 _exit / _Exit 实现

区别:函数 / 系统调用

​ _exit / _Exit 不会调用钩子函数以及不会对stdio库进行清理

命令行参数的分析:

// getopt();
int getopt(int argc, char *const argv[], 
                const char *optstring);
// getopt_long(); -> 分析长格式
int getopt_long(int argc, char *const argv[],
                const char *optstring,
                const struct option *longopts, int *longindex);

环境变量:

export 命令查看本机的环境变量

// getenv(); -> 获取
char *getenv(const char *name);
// (un)setenv(); -> (删除)修改或者增加
int setenv(const char *name,const char *value,int overwrite);
// overwrite : 是否覆写
// putenv(); -> 修改或者增加
int putenv(char *string);

C程序的存储空间布局:pmap指令

库:动态库:

​ 静态库:

​ 手工装载库:

void *dlopen(const char *filename, int flags);
int dlclose(void *handle);
char *dlerror(void);
void *dlsym(void *restrict handle, const char *restrict symbol);
// 记得 Link with -ldl

函数跳转:goto 不能实现跨函数跳转

// setjmp(); -> 设置跳转点
int setjmp(jmp_buf env);
// longjmp(); -> 跳回env并带回val
void longjmp(jmp_buf env,int val);

资源的获取以及控制:

ulimit -a 查看本机的资源量

// getrlimit(); -> 查看
int getrlimit(int resource, struct rlimit *rlp);
// setrlimit(); -> 设置
int setrlimit(int resource, const struct rlimit *rlp);
// 结构体rlp 在对普通用户和root用户的权限不同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值