首页 > 其他分享 >2022-2023-1 20201324《信息安全系统设计与实现(上)》第8章

2022-2023-1 20201324《信息安全系统设计与实现(上)》第8章

时间:2022-09-25 14:55:20浏览次数:50  
标签:文件 stat 调用 int char 2022 2023 20201324 链接

目录

1 系统调用

在操作系统中,进程以两种不同的模式运行,即内核模式和用户模式,简称Kmode和Umode。在Umode中,进程的权限非常有限。它不能执行任何需要特殊权限的操作。特殊权限的操作必须在Kmode下执行。系统调用(简称syscall)是一种允许进程进入Kmode以执行Umode不允许操作的机制。复刻子进程、修改执行映像,甚至是终止等操作都必须在内核中执行。

2 系统调用手册页

在Unix以及大多版本的Linux中,在线手册页保存在/usr/man/目录中(Goldt等1995;Kerrisk 2010,2017)。而在Ubuntu Linux中,则保存在/usr/share/man目录中。man2子目录中列出了所有系统调用手册页。sh命令man 2 NAME显示了系统调用名称的手册页。例如:

man 2 stat
man 2 open
man 2 read

man 2 stat运行结果

许多系统调用需要特别包含头文件,手册页的SYNOPSIS(概要)部分列出来这些文件。如果没有合适的头文件,会有警告

3 使用系统调用进行文件操作

系统调用必须由程序发出。它们的用法就像普通函数调用一样。每个系统调用都是一个库函数,它汇集系统调用参数,并最终向操作系统内核发出一个系统调用

列举一些简单的文件操作系统调用:

access:检查对某个文件的权限
int access(char *pathname,int mode) ;

chdir:更改目录
int chdir(const char *path);

chmod:更改某个文件的权限
int chmod(char *path,mode_t mode) ;

chown:更改文件所有人
int chown (char *name, int uid, int gid);

chroot:将(逻辑)根目录更改为路径名
int chroot(char *pathname ) ;

getcwd:获取cWD的绝对路径名
char *getcwd(char *buf, int size);

mkdir :创建目录
int mkdir(char *pathname,mode_t mode) ;

rmdir:移除目录(必须为空)
int rmdir(char *pathname );

link:将新文件名硬链接到旧文件名
int link(char *oldpath, char *newpath) ;

unlink:减少文件的链接数;如果链接数达到0,则删除文件
int unlink (char *pathname);

symlink:为文件创建一个符号链接
int symlink(char *oldpath,char *newpath);

rename:更改文件名称
int rename (char *oldpath, char *newpath);

utime:更改文件的访问和修改时间
int utime(char *pathname, struct utimebuf *time)
  
//以下系统调用需要超级用户权限

mount:将文件系统添加到挂载点目录上
int mount(char *specialfile,char *mountDir);

umount:分离挂载的文件系统
int umount (chaz *dir);

mknod:创建特殊文件
int mknod(char *path, int mode,int device);

mkdir、chdir、getcwd系统调用:

发现报错,经排查发现C语言调用mkdir、chdir、getcwd必须再另外调用几个头文件,加入后运行成功

4 常用的系统调用

stat:获取文件状态信息
int stat (char*filename, struct stat *buf)
int fstat(int tiledes,struct stat *buf)
int lstat (char*至ilename, struct stat *buf)
  
open:打开一个文件进行读、写、追加
int open(char *file, int flags, int mode)
  
close:关闭打开的文件描述符
int close(int fd)
  
read:读取打开的文件描述符
int read(int fd,char buf[ ], int count)
  
write:写入打开的文件描述符
int write(int fa,char buf[ 1, int count)
                          
lseck:重新定位文件描述符的读/写偏移量
int lseek(int fa, int offset,int whence)
                          
dup:将文件描述符复制到可用的最小描述符编号中
int dup(int oldrd);
                          
dup2:将oldfd复制到newfd中,如果newfd已打开,先将其关闭
intdup2(int oldfd, int newfd)
                          
link:将新文件硬链接到旧文件
int link ( char *o1dPath, char *newPath)
                          
unlink:取消某个文件的链接;如果文件链接数为0,则删除文件
int unlink(char *pathname) ;
                          
symlink:创建一个符号链接
int symlink(char *target, char *newpath)
                          
readlink:读取符号链接文件的内容
int readlink(char *path,char *buf,int bufsize)
                          
umask:设置文件创建掩码;文件权限为(mask & ~umask)
int umask (int umask);

5 链接文件

在Unix/Linux中,每个文件都有一个路径名。但是,Unix/Linux允许使用不同的路径名来表示用一个文件。这些文件叫作LINK(链接)文件。有两种类型的链接,即硬链接和软链接或符号链接

(1)硬链接

ln oldpath newpath

创建从newpath到oldpath的硬链接。对应的系统调用为:

link(char *oldpath,char *newpath)

硬链接文件会共享文件系统中相同的文件表示数据结构。文件链接会记录链接到同一索引结点的硬连接数量。相反,系统调用:

unlink(char *pathname)

会减少文件的链接数。如果链接变为0,文件就被完全删除。

(2)软连接

ln -s oldpath newpath #in command with the -s flag

创建从newpath到oldpath的软链接或符号链接。对应的系统调用是:

symlink(char *oldpath,chat *newpath)

newpath是LNK类型的普通文件,包含oldpath字符串。与硬链接不同,软链接适用于任何文件,包括目录。

软链接在以下情况下非常有用。
①通过一个较短的名称来访问一个经常使用的较长的路径名称,例如:

x -> aVeryLongPathnameFile

②将标准动态库名称链接到实际版本的动态库,例如:

libc.so.6 -> libc.2.7.so

当将实际动态库更改为不同版本时,库安装程序只需更改(软)链接以指向新安装的库。
软链接的一个缺点是目标文件可能不复存在了。在Linux中,会通过ls命令以适当的深色RED显示此类危险,提醒用户链接已断开。此外,如果foo -> /a/b/c是软链接,open("foo", 0)系统调用将打开被链接的文件/a/b/c,而不是链接文件自身。所以open()/read()系统调用不能读取软链接文件,反而必须要用readlink系统调用来读取软链接文件的内容。

6 stat系统调用

stat/lstat/fstat系统调用可将一个文件的信息返回。命令man 2 stat会显示stat系统调用的手册页

(1)stat系统调用的Linux开发者手册概要

#include <sys/ types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat (const char *file_name,struct stat *buf);
int fstat (int filedes,struct stat *buf) ;
int lstat(const char *file_name,struct stat *buf) ;

这些函数会返回指定文件的信息。不需要拥有文件的访问权限即可获取该信息,但是需要指向文件的路径中所有指定目录的搜索权限

(2)opendir-readdir函数

目录也是一个文件。我们应该能像其他任何普通文件一样,打开一个READ目录,然后读取和显示它的内容。然而,根据文件系统的不同,目录文件的内容可能会有不同。因此,用户可能无法正确读取和解释目录的内容。鉴于此,POSIX为目录文件指定了以下接口函数。

#include <dirent.h>
DIR *open(dirPath);     // open a directory named dirPath for READ
struct dirent *readdir(DIR *dp);    // return a dirent pointer

Linux中dirent结构体是:

struct dirent {
    u32 d_ino;  // inode number
    u16 d_reclen;
    char d_name[];
};

在dirent结构体中,POSIX只要求必须保留d_name字段。其他字段取决于具体的系统。
opendir()返回一个DIR指针dirp。每个readdir(dirp)调用返回一个dirent指针,指向目录中下一个条目的dirent结构体。当目录中没有更多条目时,则返回一个NULL指针。我们用一个例子来说明它们的用法。下面的代码段可打印目录中的所有文件名称。

#include <dirent.h>
struct dirent *ep;
DIR *dp = opendir("dirname");
while (ep = readdir(dp)) {
    printf("name=%s ", ep->d_name);
}

(3)readlink函数

Linux的open()系统调用遵循符号链接。因此,无法打开符号链接文件并读取其内容。
要想读取符号链接文件的内容,我们必须使用readlink系统调用,即:

int readlink(char *pathname, char buf[], int bufsize);

它将软链接文件的内容复制到bufsize的buf[]中,并将实际复制的字节数返回。

(4)打开文件和文件描述符

#include <sys/type.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(char *pathname, int flags, mode_t mode);

open()打开一个文件进行读、写或追加。它会返回一个进程可用的最小文件描述符,用于后续的read()、write()、lseek()和close()系统调用。标志字段必须包含下列一种访问模式、即O_RDONLY、O_WRONLY或者O_RDWR。此外,这些标志可与其他标志(O_APPEND、O_TRUNC、O_CLOEXEC)逐位进行OR组合。

(5)read()系统调用

read()将n个字节从打开的文件描述符读入用户空间中的buf[]。返回值是实际读取的字节数,如果read()失败,会返回-1。

(6)write()系统调用

write()将n个字节从用户空间中的buf[]写人文件描述符,必须打开该文件描述符进行写、读写或追加。返回值是实际写入的字节数,通常等于n个字节,如果write()失败,则为-1。

标签:文件,stat,调用,int,char,2022,2023,20201324,链接
From: https://www.cnblogs.com/cqszxy2020/p/16727852.html

相关文章