Linux第七次课

Linux中的文件操作

1、文件描述符fd

所有对设备和文件的操作都是使用文件描述符来进行的。
文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程所打开的文件的记录表;

当打开一个现存文件或创建一个新文件时,内核就向进程返回一个文件描述符

当需要读写文件时,需要把文件描述符作为参数传递给相应的函数。

一个进程默认打开3个文件描述符
0 stdin(STDIN_FILENO)
1 stdout(STDOUT_FILENO)
2 stderr(STDERR_FILENO)

查看用户进程能打开多少个文件描述(1024)
ulimit -n

查看系统文件描述符个数(100624)
这个值根据实际的操作系统确定
cat /proc/sys/fs/file-max

2、文件描述符(fd)与 文件指针(FILE*)

struct FILE
{
char *_ptr;//文件输入的下一个位置
int _cnt;//当前缓冲区的相对位置
char *_base;//指基础位置(文件的起始位置)
int _flag;//文件标志
int _file;//文件的有效性验证
int _charbuf;//检查缓冲区状况,如果缓冲区则不读取
int _bufsiz;//文件的大小
char *_tmpfname;//临时文件名
};

文件指针指向进程用户区中一个被叫做FILE结构的结构数据。FILE结构包括一个缓冲区和一个文件描述符 。而文件描述符是文件描述符表的一个索引

文件描述符转文件指针
FILE *fdopen(int filedes, const char *opentype);

文件指针转文件描述符
int fileno(FILE *stream);

3、常用的函数

表头文件
#include<unistd.h>
定义函数
int access(const char * pathname,int mode);

access:判断是否具有存取文件的权限
F_OK则是用来判断该文件是否存在

unlink(删除文件)
int unlink(const char * pathname);
成功则返回0,失败返回-1,错误原因存于errno

open:open(打开文件)
定义函数
int open( const char * pathname, int flags);
int open( const char * pathname,int flags, mode_t mode);

下列是参数flags 所能使用的旗标:
O_RDONLY 以只读方式打开文件
O_WRONLY 以只写方式打开文件
O_RDWR 以可读写方式打开文件。上述三种旗标是互斥的,也就是不可同时使用,但可与下列的旗标利用OR(|)运算符组合。
O_CREAT 若欲打开的文件不存在则自动建立该文件。
O_EXCL 如果O_CREAT 也被设置,此指令会去检查文件是否存在。文件若不存在则建立该文件,否则将导致打开文件错误。此外,若O_CREAT与O_EXCL同时设置,并且欲打开的文件为符号连接,则会打开文件失败。

参数mode 则有下列数种组合,只有在建立新文件时才会生效,此外真正建文件时的权限会受到umask值所影响,因此该文件权限应该为(mode-umaks)。
S_IRWXU 00700 权限,代表该文件所有者具有可读、可写及可执行的权限。
S_IRUSR 或S_IREAD,00400权限,代表该文件所有者具有可读取的权限。
S_IWUSR 或S_IWRITE,00200 权限,代表该文件所有者具有可写入的权限。

00700

共用5个数字来表示文件的各种权限:
第一位表示设置用户ID;
第二位表示设置组ID;
第三位表示用户自己的权限位;
第四位表示组的权限;
最后一位表示其他人的权限。
每个数字可以取1(执行权限)、2(写权限)、4(读权限)、0(无)或者是这些值的和。
例如,要创建一个用户可读、可写、可执行,但是组没有权限,其他人可以读、可以执行的文件,并设置用户ID位。那么,我们应该使用的模式是1(设置用户ID)、0(不设置组ID)、7(1+2+4,读、写、执行)、0(没有权限)、5(1+4,读、执行)即10705:

在UNIX进程中也有几组ID的概念。分别是实际用户ID,实际用户组ID,有效用户ID和有效用户组ID等等。当我们开始一个进程是,通常这个进程的有效用户ID就是这个进程的实际ID(比如我用eric用户登录,这个有效用户就我eric对应的ID)。然而当“设置用户ID位”打开以后,有效ID就是进程的程序文件对应的所有者的ID。

RUID(real user id)是启动该进程的用户的ID,它与父进程用户ID相同,除非被改变.

EUID是内核检查权限时使用的实际ID,因此它确定了进程的权限.

SSUID:设置用户ID,表示执行时设置用户ID程序的进程映像文件的所有者ID.

允许一个进程将其EUID更改为其RUID/SSUID.当然root特权进程可做任何事.

当访问一个文件时,进程的有效用户ID(Effective User ID,EUID)与文件所有者的UID进行对比.如果该用户不是所有者,那么再对GID进行比较.

文件还有一个执行时设置用户ID位(set-user-ID-on-execution)S_ISUID表示的.该位可以设置给一个可执行进程二进制文件,表示以可执行文件所有者的特权而不是用户组的特权运行(即EUID设置为文件所有者ID).exec->bprm_fill_uid()中实现.

creat:建立文件
定义函数
int creat(const char * pathname, mode_tmode);
函数说明
参数pathname指向欲建立的文件路径字符串。Creat()相当于使用下列的调用方式调用open()
open(const char * pathname ,(O_CREAT|O_WRONLY|O_TRUNC));

read:由已打开的文件读取数据
ssize_t read(int fd,void * buf ,size_t count);

read()会返回实际读到的字节数

write:将数据写入已打开的文件内)
ssize_t write (int fd,const void * buf,size_t count);

close

lseek:移动文件的读写位置
off_t lseek(int fildes,off_t offset ,int whence);

参数
whence为下列其中一种:
SEEK_SET 参数offset即为新的读写位置。
SEEK_CUR 以目前的读写位置往后增加offset个位移量。
SEEK_END 将读写位置指向文件尾后再增加offset个位移量。
当whence 值为SEEK_CUR 或SEEK_END时,参数offet允许负值的出现。
下列是教特别的使用方式:

  1. 欲将读写位置移到文件开头时:lseek(int fildes,0,SEEK_SET);
  2. 欲将读写位置移到文件尾时:lseek(int fildes,0,SEEK_END);
  3. 想要取得目前文件位置时:lseek(int fildes,0,SEEK_CUR);

fstat:由文件描述词取得文件状态
int fstat(int fildes,struct stat *buf);
执行成功则返回0,失败返回-1

struct stat

ftruncate(改变文件大小)
int ftruncate(int fd,off_t length);

函数说明
ftruncate()会将参数fd指定的文件大小改为参数length指定的大小。参数fd为已打开的文件描述符,而且必须是以写入模式打开的文件。
如果原来的文件大小比参数length大,则超过的部分会被删去。
返回值
执行成功则返回0,失败返回-1,错误原因存于errno。

案例
2、目录的遍历(file2.c)
DIR
opendir
struct dirent
d_type:1、DT_DIR
2、DT_REG

readdir
closedir

3、递归遍历目录(printdir3.c)
chdir
lstat
S_ISDIR

猜你喜欢

转载自blog.csdn.net/weixin_44545549/article/details/89414488