文件和目录

start fstart lstart函数

一旦给出pathname, start函数就返回了与此命名文件有关的信息结构

  #include <sys/start>
int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);/*能观察到符号链接*/

参数:

pathname:文件路径

fd:文件描述符

buf:存放每天与此命名文件有关信息结构的地址

返回值:

成功返回0 失败返回1

   struct stat {
mode_t st_mode; // 文件类型和访问权限
ino_t st_ino; // 指向数据块的i节点的编号
dev_t st_dev; // 设备号
dev_t st_rdev;
nlink_t st_nlink; // 硬链接数
uid_t st_uid; // 用户ID
gid_t st_gid; // 用户组ID
off_t st_size;
struct timespec st_atim; // 数据访问时间
struct timespec st_mtim; // 数据修改时间
struct timespec st_ctim; // 属性修改时间
blksize_t st_blksize; // 合适的IO块大小
blkcnt_t st_blocks; //分配了多少block
};

文件类型

普通文件(regular file):包含数据的常规文件,数据可以是文本类型的,也可以是二进制的。

目录文件(directory file):它是一个目录,保存目录相关的信息。

块设备文件(block special file):这种文件提供对硬件(如磁盘)带缓冲的访问。

字符设备文件(regular file):这种文件提供对硬件(如磁盘)不带缓冲的访问。

FIFO:这种文件用于进程间通信。有时也被称为命名管道。

套接字文件(regular file):这种文件用于网络间通信。也可以用在一台宿主机进程上的非网络通信。

符号连接(regular file):类似Windows系统的快捷方式,指向另外一个文件。

文件类型的信息包含在start中的st_mode中,可以用以下的宏函数来判断文件类型。

  S_ISREG()        /* 普通文件 */
S_ISDIR() /* 目录 */
S_ISCHR() /* 字符文件 */
S_ISBLK() /* 块文件 */
S_ISFIFO() /* 管道文件 */
S_ISLINK() /* 链接文件 */
S_ISSOCK() /* 网络套接字 */

如果要确定IPC对象的类型用以下宏函数,但是参数改为指向start结构体的指针。

  S_TYPEISMQ()      /*消息队列*/
S_TYPEISSEM() /*信号量*/
S_TYPEISSHM() /*共享存储对象*/

简单用法:

  #include "apue.h"
int
main(int argc, char *argv[])
{
int i;
struct stat buf;
char *ptr; for (i = 1;i < argc; i++) {
printf("%s: ", argv[i]);
if (lstat(argv[i], &buf) < 0) {
err_ret("lstat error");
continue;
}
if (S_ISREG(buf.st_mode))
ptr = "regular";
else if (S_ISDIR(buf.st_mode))
ptr = "directory";
else if (S_ISCHR(buf.st_mode))
ptr = "character special";
else if (S_ISBLK(buf.st_mode))
ptr = "block special";
else if (S_ISFIFO(buf.st_mode))
ptr = "fifo";
else if (S_ISLNK(buf.st_mode))
ptr = "symbolic link";
else if (S_ISSOCK(buf.st_mode))
ptr = "socket";
else
ptr = "** unknown mode **";
printf("%s\n", ptr);
}
exit(0);
}

输入:./a.out pathname1 pathname2

文件访问权限

所有文件类型都有文件访问权限,每个文件有九个文件访问权限位,可将其分为三类。分别表示用户u 组g 其他o的读写执行权限

我们用名字来打开任意类型的文件时,对该名字所包含的每一个目录包括当前目录,都必须具有执行权限

读权限用于目录可以读取目录包含的文件,例如ls,对以一个普通文件的读权限决定了我们打开文件后能否进行读操作

在目录中创建一个文件,必须对该目录具有写权限和执行权限,在目录中删除一个文件时不需要对该文件的读写权限

想要打开一个文件必须对该文件具有可执行权限,想要对该文件修改内容(对目录来说是创建或者删除文件),必须在打开该文件

或目录的基础上(具有执行权限)具有写权限才可以,而想要读取文件则只需要对该文件有执行权限和读权限。

进程每次操作一个文件时,内核就会进行文件权限测试,即把文件的所有者(st_uid st_gid)和进程的有效ID(有效用户ID和有效组ID)对比

  • 如果进程的有效用户id为0(超级用户)则允许访问
  • 进程的有效ID等于文件所有者的ID(进程拥有这个文件),如果文件所有者适当的访问权限被设置(读写执行权限)则允许访问
  • 进程有效组ID等于文件的组ID,判断方法同上
  • 其他用户适当的访问权限被设置,也允许访问

新文件和目录的所有权

创建新文件时,新文件的组id可以是进程的有效组id也可以是他所在目录的id,取决于设置

access函数

判断当前用户是否具有以某种模式访问某个文件的权限

  #include<unistd.h>
int access(const char *pathname, int mode);

参数:

mode可取值如下R_OK、W_OK、X_OK、F_OK(测试文件是否存在)

返回值:

能访问则返回0,不能访问则返回-1

umask函数

umask为进程创建新文件时对文件模式创建屏蔽字,修改文件权限时没有效果,并返回以前的值

  #include<sys_start.h>
mode_t umask(mode_t cmask);

返回值:

以前的文件模式屏蔽字

  /* 例子 */
mode_t mode = umask(0111);
if(creat("a.txt",0777)<0)/* 原来设置的权限是0777,那么最终的结果是0777 - 0111 = 0666*/
err_sys("creat error");
umask(mode); /* 恢复修改之前的umask数值 */

chmod和fchmod函数

可以更改现有文件的访问权限 chmod修改指定文件的访问权限,fchmod修改已经打开的文件的访问权限(打开文件返回文件描述符)

  #include <sys_start.h>
int chmod(const char* pathname ,mode_t mode);
int fchmod(int fd,mode_t mode);

返回值:

修改成功返回0,失败返回-1

想要修改一个文件的权限位,进程的有效id必须等于文件所有者的id,或者该进程拥有超级用户权限

mode 说明
S_ISUID 执行时设置用户id
S_ISGID 执行时设置组id
S_ISVTX 保存正文
---- ----
S_IRWXU 用户读写执行
S_IRUSR 用户读
S_IWUSR 用户写
S_IXUSR 用户执行
---- ----
S_IRWXG 组读写执行
S_IWGRP 组写
S_IXGRP 组执行
S_IRGRP 组读
---- ----
S_IRWXO 其他读写执行
S_IWOTH 其他写
S_IXOTH 其他执行
S_IROTH 其他读

保存正文:

该程序第一次执行并结束时,正文部分的一个副本仍然被保留在交换区,这使得下次执行时该程序能较快的装入内存区

现在已经不需要这项技术

对一个目录设置了粘住位,你只有在拥有此文件,拥有此目录,是超级用户才能删除或者更名该目录下的文件

chown fchown lchown 函数

修改文件的用户id和组id

  #include<unistd>
int chown(const char* pathname,uid_t owner,gid_t group);
int fchown(int fd , uid_t owner ,gid_t group);
/*lchown更改符号链接本身的所有者,而不是符号链接指向的文件*/
int lchown(const char* pathname, uid_t owner , gid_t group);

返回值:

成功返回0,失败返回-1

只有超级用户进程才能修改文件的用户id

进程拥有此文件,可以修改文件的组id,但只能该到自己所属的组

文件长度

start结构体中的st_size 表示以字节为单位的文件长度且只对普通文件目录文件和符号链接有意义

普通文件:文件长度可以是0

目录:文件长度通常是一个数(16或者512的整数倍)

符号链接:文件长度是文件名的实际字节数,如usr/lib文件长度为7(并不包含c语言最后的null)

大部分unix系统提st_blksize(对文件较合适的块长度)和st_blocks(所分配实际的块的个数)

文件系统

我们可以把一个磁盘分为多个分区,每一个分区都有一个文件系统

i节点是固定长度的记录项,他包含了文件的大部分信息,并指向该文件要包含的数据块

图示为硬链接

每个目录块都包含了一个以文件名和它i节点号为表项的表

每个i节点都有一个链接计数,表示有多少指向该i节点的目录项数,当这个记数减少到0的时候文件才会彻底删除(解除对一个文件的链接)

link,unlink,remove和rename函数

任何一个文件可以有多个目录项指向其i节点,创建一个指向现有文件的链接:link

  #include<unistd.h>
int link(const char *existingpath ,const char* newpath );

引用现有的文件existingpath创建一个新的文件newpath,如果newpath已经存在返回出错

返回值:

成功返回0,失败返回-1

删除一个现有的目录项使用ulink

  #include <unistd.h>
int ulink(const char * pathname);

删除目录项,并将pathname引用的文件链接计数-1(如果其它地方还是有链接还是能访问此文件)

如果设置了粘住位只有在拥有该文件,具有超级管理员权限才可以删除

返回值:

成功返回0,失败返回-1

remove函数

解除该路径对一个文件或者一个目录的链接

  #include <stdio.h>
int remove (const char *pathname);

返回值:

成功返回0,失败返回-1

rename函数

文件或者目录更名

  #include<stdio.h>
int rename (const char* oldname,const char new name);

返回值:

成功返回0,失败返回-1

符号链接

符号链接就是一个指向文件的间接指针

  # include <unistd.h>
int symlink(const char * path ,const char * sympath);

创建一个指向path的新目录项sympath,创建时并不要求path存在,path和sympath不一定在一个文件系统中

  /*读取符号链接*/
#include <unist.h>
size_t readlink(const char * restrict pathname , char restrict buf,size_t bufsize );

返回值:

成功则返回读到的字节数,失败则返回-1

文件的时间

st_atime、文件数据的最后访问时间

st_mtime、文件数据的最后修改时间

st_ctime、i节点状态的最后修改时间

目录相关函数

  /*dirent至少有如下两个成员*/
struct dirent{
ino_t d_ino;/*节点*/
char d_name [NAME_MAX+1];/*文件名*/
} #include <dirent.h> /* 打开一个目录 */
DIR *opendir(const char *name); // 成功返回指针,失败返回NULL
DIR *fdopendir(int fd); // 成功返回指针,失败返回NULL /* 读取目录中的内容,如文件、子目录 */
struct dirent *readdir(DIR *dirp); // 成功返回指针,失败返回NULL /* 让目前的读取位置还原到开头的读取位置 */
void rewinddir(DIR *dirp); /* 设置相对于开头偏移值为pos的读取位置 */
void seekdir(DIR *dirp, long int pos); /* 关闭目录 */
int closedir(DIR *dirp); // 成功时返回0,失败返回-1 /* 例子 */
DIR* dir = opendir("../");
struct dirent* ent;
while(ent=readdir(dir)) // 1 读, 2 =,3 判断ent是否为0
{
printf("%d, %s\n", ent->d_type, ent->d_name);
} // d_tpye == 4 的是目录
closedir(dir);

chdir、fchdir、getcwd函数

用以下两个函数可以改变当前工作目录

  #include<unist.h>
int chdir(const char * pathname);
int fchdir(int fd);

getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数size为buf的空间大小。

缓冲区必须有足够大的空间足以容纳下绝对路径加上一个null ,否则返回出错

#include<unist.h>

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

unix环境高级编程第四章笔记的更多相关文章

  1. unix环境高级编程第六章笔记

    口令文件 阴影口令 组文件 附属组ID 登录账户记录 系统标识 口令文件<\h2> /etc/passwd文件是UNIX安全的关键文件之一.该文件用于用户登录时校验用户的口令,文件中每行的 ...

  2. unix环境高级编程第三章笔记

    文件描述符 1.文件描述符的概念 对于内核而言,所有打开的文件都会用一个文件描述符来引用,打开或和创建一个新文件的时候,内核会给进程返回一个文件描述符,而当使用read write时,可以使用这个文件 ...

  3. UNIX环境高级编程 第8章 进程控制

    本章是UNIX系统中进程控制原语,包括进程创建.执行新程序.进程终止,另外还会对进程的属性加以说明,包括进程ID.实际/有效用户ID. 进程标识 每个进程某一时刻在系统中都是独一无二的,它们之间是用一 ...

  4. UNIX环境高级编程 第7章 进程环境

    本章涉及C/C++程序中main函数是如何被调用的.命令行参数如何传递给main函数.程序的内存空间布局.程序如何使用环境变量.程序如何终止退出. main函数 C程序或C++程序总是从main函数开 ...

  5. UNIX环境高级编程 第13章 守护进程

    守护进程daemon是一种生存周期很长的进程.它们通常在系统引导时启动,在系统关闭时终止.守护进程是没有终端的,它们一直在后台运行. 守护进程的特征 在Linux系统中,可以通过命令 ps -efj ...

  6. UNIX环境高级编程 第9章 进程关系

    在第8章学习了进程的控制原语,通过各种进程原语可以对进程进行控制,包括新建进程.执行新程序.终止进程等.在使用fork( )产生新进程后,就出现了进程父子进程的概念,这是进程间的关系.本章更加详细地说 ...

  7. UNIX环境高级编程 第6章 系统数据文件和信息

    UNIX系统的正常运作需要用到大量与系统有关的数据文件,例如系统用户账号.用户密码.用户组等文件.出于历史原因,这些数据文件都是ASCII文本文件,并且使用标准I/O库函数来读取. 口令文件 /etc ...

  8. UNIX环境高级编程 第5章 标准I/O库

    本章是关于C语言标准I/O库的,之所以在UNIX类系统的编程中会介绍C语言标准库,主要是因为UNIX和C之间具有密不可分的关系.由于UNIX系统存在很多实现,而每个实现都有自己的标准I/O库,为了统一 ...

  9. UNIX环境高级编程 第4章 文件和目录

    第三章说明了关于文件I/O的基本函数,主要是针对普通regular类型文件.本章描述文件的属性,除了regular文件还有其他类型的文件. 函数stat.fstat.fstatat和lstat sta ...

随机推荐

  1. 数仓建设中最常用模型--Kimball维度建模详解

    数仓建模首推书籍<数据仓库工具箱:维度建模权威指南>,本篇文章参考此书而作.文章首发公众号:五分钟学大数据,公众号中发送"维度建模"即可获取此书籍第三版电子书 先来介绍 ...

  2. Spring Boot 计划任务中的一个“坑”

    计划任务功能在应用程序及其常见,使用Spring Boot的@Scheduled 注解可以很方便的定义一个计划任务.然而在实际开发过程当中还应该注意它的计划任务默认是放在容量为1个线程的线程池中执行, ...

  3. 【SpringMVC】SpringMVC 响应数据

    SpringMVC 响应数据 文章源码 返回值分类 返回值是字符串 Controller 方法返回字符串可以指定逻辑视图的名称,通过视图解析器解析为物理视图的地址. @Controller @Requ ...

  4. 基于SVM的字母验证码识别

    基于SVM的字母验证码识别 摘要 本文研究的问题是包含数字和字母的字符验证码的识别.我们采用的是传统的字符分割识别方法,首先将图像中的字符分割出来,然后再对单字符进行识别.首先通过图像的初步去噪.滤波 ...

  5. python学习笔记 | selenium各浏览器驱动下载地址

    Chrome http://chromedriver.storage.googleapis.com/index.html 不同的Chrome的版本对应的chromedriver.exe 版本也不一样, ...

  6. ctfhub技能树—web前置技能—http协议—302跳转

    开启靶机 打开环境,查看显示 点击Give me Flag后发生跳转 根据题目提示为HTTP临时重定向 简单记录一下HTTP临时重定向是什么 HTTP重定向:服务器无法处理浏览器发送过来的请求(req ...

  7. 使用SimpleUpdater实现现有程序升级功能

    项目:https://github.com/iccfish/FSLib.App.SimpleUpdater C/S程式一般需要部署在多台机器上,如果程式有变动,需要一台一台重新安装,相当麻烦,如果我们 ...

  8. Vue MVVM模型原理

    最近反思了下自己,觉得自己很急躁,学技术总是觉得能用就行了,其实这样很不好,总是这样,就永远只能当用轮子的人.好了,废话不多说,转入正题: 要理解MVVM的原理,首先要理解它是什么,怎么运作起来的: ...

  9. Percona Toolkit工具使用

    Percona Toolkit简称pt工具-PT-Tools,是Percona公司开发用于管理MySQL的工具,功能包括检查主从复制的数据一致性.检查重复索引.定位IO占用高的表文件.在线DDL等 下 ...

  10. 小程序map学习:使用map获取当前位置并显示出来

    在小程序开发的过程中,我碰到过一个做map的需求,在我开发的时候我碰到了一些问题,这里总结出来,给大家一些解决方法. 简易小程序dome下载 代码片段分享: js部分: var amapFile = ...