系统调用方式遵循RISC-V ABI,即调用号存放在a7寄存器中,6个参数分别储存在a0-a5寄存器 中,返回值保存在a0中。
主要参考了Linux 5.10 syscalls,详细请参见:https://man7.org/linux/man-pages/man2/syscalls.2.html
功能:获取当前工作目录;
输入:
-
char *buf:一块缓存区,用于保存当前工作目录的字符串。当buf设为NULL,由系统来分配缓存区。
-
size:buf缓存区的大小。
返回值:成功执行,则返回当前工作目录的字符串的指针。失败,则返回NULL。
char *buf, size_t size;
long ret = syscall(SYS_getcwd, buf, size);
功能:创建管道;
输入:
- fd[2]:用于保存2个文件描述符。其中,fd[0]为管道的读出端,fd[1]为管道的写入端。
返回值:成功执行,返回0。失败,返回-1。
int fd[2];
int ret = syscall(SYS_pipe2, fd, 0);
功能:复制文件描述符;
输入:
- fd:被复制的文件描述符。
返回值:成功执行,返回新的文件描述符。失败,返回-1。
int fd;
int ret = syscall(SYS_dup, fd);
功能:复制文件描述符,并指定了新的文件描述符;
输入:
- old:被复制的文件描述符。
- new:新的文件描述符。
返回值:成功执行,返回新的文件描述符。失败,返回-1。
int old, int new;
int ret = syscall(SYS_dup3, old, new, 0);
功能:切换工作目录;
输入:
- path:需要切换到的目录。
返回值:成功执行,返回0。失败,返回-1。
const char *path;
int ret = syscall(SYS_chdir, path);
功能:打开或创建一个文件;
输入:
-
fd:文件所在目录的文件描述符。
-
filename:要打开或创建的文件名。如为绝对路径,则忽略fd。如为相对路径,且fd是AT_FDCWD,则filename是相对于当前工作目录来说的。如为相对路径,且fd是一个文件描述符,则filename是相对于fd所指向的目录来说的。
-
flags:必须包含如下访问模式的其中一种:O_RDONLY,O_WRONLY,O_RDWR。还可以包含文件创建标志和文件状态标志。
-
mode:文件的所有权描述。详见
man 7 inode
。
返回值:成功执行,返回新的文件描述符。失败,返回-1。
int fd, const char *filename, int flags, mode_t mode;
int ret = syscall(SYS_openat, fd, filename, flags, mode);
功能:关闭一个文件描述符;
输入:
- fd:要关闭的文件描述符。
返回值:成功执行,返回0。失败,返回-1。
int fd;
int ret = syscall(SYS_close, fd);
功能:获取目录的条目;
输入:
-
fd:所要读取目录的文件描述符。
-
buf:一个缓存区,用于保存所读取目录的信息。缓存区的结构如下:
struct dirent { uint64 d_ino; // 索引结点号 int64 d_off; // 到下一个dirent的偏移 unsigned short d_reclen; // 当前dirent的长度 unsigned char d_type; // 文件类型 char d_name[]; //文件名 };
-
len:buf的大小。
返回值:成功执行,返回读取的字节数。当到目录结尾,则返回0。失败,则返回-1。
int fd, struct dirent *buf, size_t len
int ret = syscall(SYS_getdents64, fd, buf, len);
功能:从一个文件描述符中读取;
输入:
- fd:要读取文件的文件描述符。
- buf:一个缓存区,用于存放读取的内容。
- count:要读取的字节数。
返回值:成功执行,返回读取的字节数。如为0,表示文件结束。错误,则返回-1。
int fd, void *buf, size_t count;
ssize_t ret = syscall(SYS_read, fd, buf, count);
功能:从一个文件描述符中写入;
输入:
- fd:要写入文件的文件描述符。
- buf:一个缓存区,用于存放要写入的内容。
- count:要写入的字节数。
返回值:成功执行,返回写入的字节数。错误,则返回-1。
int fd, const void *buf, size_t count;
ssize_t ret = syscall(SYS_write, fd, buf, count);
功能:创建文件的链接;
输入:
- olddirfd:原来的文件所在目录的文件描述符。
- oldpath:文件原来的名字。如果oldpath是相对路径,则它是相对于olddirfd目录而言的。如果oldpath是相对路径,且olddirfd的值为AT_FDCWD,则它是相对于当前路径而言的。如果oldpath是绝对路径,则olddirfd被忽略。
- newdirfd:新文件名所在的目录。
- newpath:文件的新名字。newpath的使用规则同oldpath。
- flags:在2.6.18内核之前,应置为0。其它的值详见
man 2 linkat
。
返回值:成功执行,返回0。失败,返回-1。
int olddirfd, char *oldpath, int newdirfd, char *newpath, unsigned int flags
int ret = syscall(SYS_linkat, olddirfd, oldpath, newdirfd, newpath, flags);
功能:移除指定文件的链接(可用于删除文件);
输入:
- dirfd:要删除的链接所在的目录。
- path:要删除的链接的名字。如果path是相对路径,则它是相对于dirfd目录而言的。如果path是相对路径,且dirfd的值为AT_FDCWD,则它是相对于当前路径而言的。如果path是绝对路径,则dirfd被忽略。
- flags:可设置为0或AT_REMOVEDIR。
返回值:成功执行,返回0。失败,返回-1。
int dirfd, char *path, unsigned int flags;
syscall(SYS_unlinkat, dirfd, path, flags);
功能:创建目录;
输入:
- dirfd:要创建的目录所在的目录的文件描述符。
- path:要创建的目录的名称。如果path是相对路径,则它是相对于dirfd目录而言的。如果path是相对路径,且dirfd的值为AT_FDCWD,则它是相对于当前路径而言的。如果path是绝对路径,则dirfd被忽略。
- mode:文件的所有权描述。详见
man 7 inode
。
返回值:成功执行,返回0。失败,返回-1。
int dirfd, const char *path, mode_t mode;
int ret = syscall(SYS_mkdirat, dirfd, path, mode);
- 功能:卸载文件系统;
- 输入:指定卸载目录,卸载参数;
- 返回值:成功返回0,失败返回-1;
const char *special, int flags;
int ret = syscall(SYS_umount2, special, flags);
- 功能:挂载文件系统;
- 输入:
- special: 挂载设备;
- dir: 挂载点;
- fstype: 挂载的文件系统类型;
- flags: 挂载参数;
- data: 传递给文件系统的字符串参数,可为NULL;
- 返回值:成功返回0,失败返回-1;
const char *special, const char *dir, const char *fstype, unsigned long flags, const void *data;
int ret = syscall(SYS_mount, special, dir, fstype, flags, data);
- 功能:获取文件状态;
- 输入:
- fd: 文件句柄;
- kst: 接收保存文件状态的指针;
struct kstat {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
unsigned long __pad;
off_t st_size;
blksize_t st_blksize;
int __pad2;
blkcnt_t st_blocks;
long st_atime_sec;
long st_atime_nsec;
long st_mtime_sec;
long st_mtime_nsec;
long st_ctime_sec;
long st_ctime_nsec;
unsigned __unused[2];
};
- 返回值:成功返回0,失败返回-1;
int fd;
struct kstat kst;
int ret = syscall(SYS_fstat, fd, &kst);
- 功能:创建一个子进程;
- 输入:
- flags: 创建的标志,如SIGCHLD;
- stack: 指定新进程的栈,可为0;
- ptid: 父线程ID;
- tls: TLS线程本地存储描述符;
- ctid: 子线程ID;
- 返回值:成功则返回子进程的线程ID,失败返回-1;
pid_t ret = syscall(SYS_clone, flags, stack, ptid, tls, ctid)
- 功能:执行一个指定的程序;
- 输入:
- path: 待执行程序路径名称,
- argv: 程序的参数,
- envp: 环境变量的数组指针
- 返回值:成功不返回,失败返回-1;
const char *path, char *const argv[], char *const envp[];
int ret = syscall(SYS_execve, path, argv, envp);
- 功能:等待进程改变状态;
- 输入:
- pid: 指定进程ID,可为-1等待任何子进程;
- status: 接收状态的指针;
- options: 选项:WNOHANG,WUNTRACED,WCONTINUED;
- 返回值:成功则返回进程ID;如果指定了WNOHANG,且进程还未改变状态,直接返回0;失败则返回-1;
pid_t pid, int *status, int options;
pid_t ret = syscall(SYS_wait4, pid, status, options);
- 功能:触发进程终止,无返回值;
- 输入:终止状态值;
- 返回值:无返回值;
int ec;
syscall(SYS_exit, ec);
- 功能:获取父进程ID;
- 输入:系统调用ID;
- 返回值:成功返回父进程ID;
pid_t ret = syscall(SYS_getppid);
- 功能:获取进程ID;
- 输入:系统调用ID;
- 返回值:成功返回进程ID;
pid_t ret = syscall(SYS_getpid);
- 功能:修改数据段的大小;
- 输入:指定待修改的地址;
- 返回值:成功返回0,失败返回-1;
uintptr_t brk;
uintptr_t ret = syscall(SYS_brk, brk);
- 功能:将文件或设备取消映射到内存中;
- 输入:映射的指定地址及区间;
- 返回值:成功返回0,失败返回-1;
void *start, size_t len
int ret = syscall(SYS_munmap, start, len);
- 功能:将文件或设备映射到内存中;
- 输入:
- start: 映射起始位置,
- len: 长度,
- prot: 映射的内存保护方式,可取:PROT_EXEC, PROT_READ, PROT_WRITE, PROT_NONE
- flags: 映射是否与其他进程共享的标志,
- fd: 文件句柄,
- off: 文件偏移量;
- 返回值:成功返回已映射区域的指针,失败返回-1;
void *start, size_t len, int prot, int flags, int fd, off_t off
long ret = syscall(SYS_mmap, start, len, prot, flags, fd, off);
- 功能:获取进程时间;
- 输入:tms结构体指针,用于获取保存当前进程的运行时间数据;
- 返回值:成功返回已经过去的滴答数,失败返回-1;
struct tms *tms;
clock_t ret = syscall(SYS_times, tms);
- 功能:打印系统信息;
- 输入:utsname结构体指针用于获得系统信息数据;
- 返回值:成功返回0,失败返回-1;
struct utsname *uts;
int ret = syscall(SYS_uname, uts);
- 功能:让出调度器;
- 输入:系统调用ID;
- 返回值:成功返回0,失败返回-1;
int ret = syscall(SYS_sched_yield);
- 功能:获取时间;
- 输入: timespec结构体指针用于获得时间值;
- 返回值:成功返回0,失败返回-1;
struct timespec *ts;
int ret = syscall(SYS_gettimeofday, ts, 0);
- 功能:执行线程睡眠,sleep()库函数基于此系统调用;
- 输入:睡眠的时间间隔;
struct timespec {
time_t tv_sec; /* 秒 */
long tv_nsec; /* 纳秒, 范围在0~999999999 */
};
- 返回值:成功返回0,失败返回-1;
const struct timespec *req, struct timespec *rem;
int ret = syscall(SYS_nanosleep, req, rem);
static inline _u64 internal_syscall(long n, _u64 _a0, _u64 _a1, _u64 _a2, _u64
_a3, _u64 _a4, _u64 _a5) {
register _u64 a0 asm("a0") = _a0;
register _u64 a1 asm("a1") = _a1;
register _u64 a2 asm("a2") = _a2;
register _u64 a3 asm("a3") = _a3;
register _u64 a4 asm("a4") = _a4;
register _u64 a5 asm("a5") = _a5;
register long syscall_id asm("a7") = n;
asm volatile ("ecall" : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"
(a5), "r"(syscall_id));
return a0;
}