概述
当我们在shell写入一个程序的时候
#include <stdio.h>
此处调用了stdio.h的C标准库,他是存在在glibc中的库函数,他里面通过一些预处理最终会调用系统调用函数,其中,系统调用函数一般是放在
#include <unistd.h>
当然,我们也可以直接写一个系统调用函数调用内核函数
ssize_t write(int fd, const void *buf, size_t count);
/*************************************************************************
> File Name: hello.c
> Author: liuhao
> Mail: 2226958871@qq.com
> Created Time: Sat 19 Jun 2021 11:02:59 AM CST
************************************************************************/
#include<stdio.h>
#include <unistd.h>
int main() {
printf("Hello Worldn");
write(1, "Hello Worldn", 20);
return 0;
}
➜ C ./a.out
Hello World
Hello World
以write为例,系统调用函数和内核函数有一个接口来调用内核函数sys_write,该方法会直接调用硬件(比如write,会直接写入到屏幕上进行显示)
- open: 打开文件或设备
- read: 从打开的文件或设备中读取数据
- write: 向打开的文件或设备中写入数据
- close:关闭文件或者设备
- ioctl:把控制信息传递给设备驱动文件
具体执行讲解可见ELF可执行文件执行全过程
strace ./a.out
execve("./a.out", ["./a.out"], 0x7fffc106e0d0 /* 27 vars */) = 0
brk(NULL) = 0x564fe1e53000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fff87737bd0) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=102952, ...}) = 0
mmap(NULL, 102952, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0272e45000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF2113 3 >