ILD

fs related systemcall
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2025-2-16 站点:Inside Linux Development

文件操作系统调用

文件操作相关的系统调用,都在在内核源码的fs目录下的.c文件中。可以搜索一下

$ grep -nr SYSCALL_DEFINE fs/*.c


整理如下:

fs/aio.c

io_setup()

io_destroy()

io_submit()

io_cancel()

io_getevents()

io_pgetevents()

io_pgetevents_time32()

io_getevents_time32()

fs/d_path.cgetcwd()
fs/eventfd.c

eventfd2()

eventfd()

fs/eventpoll.c

epoll_create1()

epoll_create()

epoll_ctl()

epoll_wait()

epoll_pwait()

epoll_pwait2()

fs/exec.c

uselib()

execve()

execveat()

fs/fcntl.c

fcntl()

fcntl64()

fhandle

name_to_handle_at()

open_by_handle_at()

fs/file.c

dup3()

dup2()

dup()

fs/filesystem.csysfs()
fs/fsopen.c

fsopen()

fspick()

fsconfig()

fs/ioctl.cioctl()
fs/locks.cflock()
fs/namei.c

mknodat()/mknod()

mkdirat()/mkdir()

rmdir()

unlinkat()/unlink()

symlinkat()/symlink()

linkat()/link()

renameat2()/renameat()/rename()

fs/namespace.c

umount()

oldumount()

open_tree()

mount()

fsmount()

move_mount()

pivot_root()

mount_setattr()

statmount()

listmount()

fs/open.c

truncate()/truncate64()

ftruncate()/ftruncate64()

fallocate()

faccessat()/faccessat2()

access()

chdir()

fchdir()

chroot()

fchmod()/fchmodat2()/fchmodat()

chmod

fchownat()

chown()/lchown/fchown

open()/openat()/openat2()

creat()

close()

close_range()

vhangup()

fs/pipe.c

pipe2()

pipe()

fs/readdir.c

old_readdir()

getdents()

getdents64()

fs/read_write.c

lseek()

llseek()

read()

write()

pread64()

pwrite64()

readv/writev

preadv/preadv2

pwritev/pwritev2

sendfile/sendfile64

copy_file_rnage

fs/select.c

select

pselect6/pselect6_time32

poll/ppoll

ppoll_time32

fs/signalfd.c

signalfd4()

signalfd()

fs/splice.c

vmsplice()

splice()

tee()

fs/stat.c

stat()/lstat()/fstat()

newstat/newlstat/newfstat

netfstatat

readlink/readlinkat

stat64/lstat64/fstat64

fstatat64

statx

fs/statfs.c

statfs/statfs64

fstatfs/fstatfs64

ustat

fs/sync.c

sync()

syncfs()

fsync()

fdatasync()

sync_file_range()

sync_file_range2()

fs/timerfd.c

timerfd_create()

timerfd_settime()

timerfd_gettime()

timerfd_settime32()

timerfd_gettime32()

fs/userfaultfd.cuserfaultfd()
fs/utimes.c

utimensat

futimesat

utimes

utime32

utimensat_time32

futimesat_time32

utimes_tim32

fs/xattr.c

setxattr/lsetxattr/fsetxattr

lgetxattr/getxattr/fgetxattr

listxattr/llistxattr/flistxattr

removexattr

lremovexattr

fremovexattr


新学习到的几个系统调用:

name_to_handle_at/open_by_handle_at


       int name_to_handle_at(int dirfd, const char *pathname,
                             struct file_handle *handle,
                             int *mount_id, int flags);
       int open_by_handle_at(int mount_fd, struct file_handle *handle,
                             int flags);

name_to_handle_at(),返回特定文件的透明的file handle

           struct file_handle {
               unsigned int  handle_bytes;   /* Size of f_handle [in, out] */
               int           handle_type;    /* Handle type [out] */
               unsigned char f_handle[0];    /* File identifier (sized by
                                                caller) [out] */
           };


这个handle唯一标识了这个文件。然后可以用这个handle,去执行open动作。这样就免去了用路径去标识。在NFS系统中很有用。


一个例子,打印文件的file handle内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#define _GNU_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
 
int main(int argc, char **argv)
{
    char *path = argv[1];
    struct file_handle handle = {
        .handle_bytes = 0,
    };
    int ret;
    int mount_id = 0;
    struct file_handle *phandle;
 
    ret = name_to_handle_at(AT_FDCWD, path, &handle, &mount_id, 0);
    if (ret < 0) {
        if (errno != EOVERFLOW) {
            fprintf(stderr, "name_to_handle_at() get handle bytes failed: %m\n");
            return 1;
        }
    }
 
    phandle = calloc(1, sizeof(struct file_handle) + handle.handle_bytes);
    if (!phandle) {
        fprintf(stderr, "malloc() failed: %m\n");
        return 1;
    }
 
    phandle->handle_bytes = handle.handle_bytes;
 
    ret = name_to_handle_at(AT_FDCWD, path, phandle, &mount_id, 0);
    if (ret < 0) {
        fprintf(stderr, "name_to_handle_at() failed: %m\n");
        return 1;
    }
 
    printf("path %s\n", path);
    printf("mount_id: %d\n", mount_id);
    printf("handle bytes: %d\n", phandle->handle_bytes);
    printf("handle type: %d\n", phandle->handle_type);
    printf("handle:");
    for (ret = 0; ret < phandle->handle_bytes; ret++)
        printf(" %02x", phandle->f_handle[ret]);
    printf("\n");
    return 0;
}


$ ./a.out file_handle.c
path file_handle.c
mount_id: 50
handle bytes: 20
handle type: 77
handle: 7f 78 e8 00 00 00 00 00 01 01 00 00 00 00 00 00 3b 01 01 00

$ stat file_handle.c
  File: file_handle.c
  Size: 1136          Blocks: 8          IO Block: 4096   regular file
Device: 0,50    Inode: 15235199    Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/  yuanjp)   Gid: ( 1000/  yuanjp)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2025-02-16 11:05:43.151116796 +0800
Modify: 2025-02-16 11:05:41.245140071 +0800
Change: 2025-02-16 11:05:41.255139948 +0800
 Birth: 2025-02-16 11:05:41.245140071 +0800

$ printf "%x\n" 15235199
e8787f


在这个btrfs里面。可以看到handle bytes是20个字节。前8个字节是inode id。后面0101是257是subvolume id。


userfaultfd

这个接口创建一个处理page faults的文件描述符。通常用来先user space paging。

当一个线程发生page faults时,可以在另外一个线程接收相关消息,然后分配内存。


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.