当前位置: 首页 > 科技观察

要想成为Linux下的编程高手,就必须对各种系统调用有透彻的了解

时间:2023-03-18 02:37:28 科技观察

什么是系统调用?Linux内核中设置了一组实现各种系统功能的子程序,称为系统调用。用户可以通过系统调用命令在自己的应用程序中调用它们。从某种角度来看,系统调用与普通的函数调用非常相似。唯一不同的是,系统调用由操作系统核心提供,运行在核心状态;而普通的函数调用是由函数库或用户自己提供的,运行在用户态。Linux内核也提供了一些C语言函数库。这些库有一些系统调用的封装和扩展。由于这些库函数与系统调用密切相关,所以习惯上称这些函数为系统调用。为什么要使用系统调用?其实很多我们习以为常的C语言标准函数在Linux平台上都是通过系统调用来实现的,所以想要深入了解系统的底层原理,掌握各种系统调用是初步要求。再者,如果你想成为Linux下的编程高手,也就是我们常说的Hacker,标志之一就是要对各种系统调用有深入的了解。即使去掉上面的原因,你会发现在普通的编程中,很多时候系统调用是实现你的想法的一种简洁有效的方式,所以如果可能的话,你应该尽可能多地掌握系统调用,这将有助于你在编程过程中得到了意想不到的帮助。系统调用如何工作?通常,进程不能访问内核。它不能访问内核占用的内存空间,也不能调用内核函数。CPU硬件决定了这一点(这就是它被称为“保护模式”的原因)。系统调用是这些规则的一个例外。其原理是进程先将合适的值填充到寄存器中,然后调用一条特殊的指令,该指令会跳转到内核中预先定义好的位置(当然这个位置是用户进程可读但不可写的).在IntelCPU中,这是通过中断0x80实现的。硬件知道,一旦你跳到这一点,你就不是在受限模式下作为用户运行,而是作为操作系统的内核——所以你可以做任何你想做的事。进程可以跳转到的内核位置称为sysem_call。该进程检查系统调用号,它告诉内核该进程正在请求哪个服务。然后,它查看系统调用表(sys_call_table),找到被调用内核函数的入口地址。然后,调用该函数,等待它返回,做一些系统检查,最后返回到进程(或另一个进程,如果进程超时)。具体流程如下图所示:如何使用系统调用?我们先看一个例子:这是因为time系统调用实际上已经在time.h中以库函数的形式实现了,省去了我们调用_syscall1宏展开获取函数原型的步骤。大多数系统调用都是在各种C语言函数库中实现的,所以一般情况下,我们可以像调用普通库函数一样调用系统调用,只有在极少数情况下,我们才有机会使用到_syscall*()这些宏。调用性能问题系统调用需要从用户空间落入内核空间,处理后需要返回用户空间。除了系统调用服务程序的实际耗时外,陷阱/返回过程和系统调用处理程序(检查系统调用表、存储\恢复用户站点)也需要花费一些时间,这些时间加上最多一个系统调用。响应速度。系统调用并不比其他用户程序要求高,因为它需要落入内核执行,所以和其他内核程序一样要求代码简洁,执行速度快。幸运的是,Linux有着不可思议的上下文切换速度,使其进入和退出内核都被优化得简洁高效;同时,所有的Linux系统调用处理程序和每个系统调用本身也非常简洁。在大多数情况下,Linux系统调用的性能是可以接受的,但是对于一些对性能要求非常高的应用程序来说,虽然想要使用系统调用的服务,但是希望能够加快响应速度,避免陷入/返回和系统调用。调用处理程序带来的开销,所以内核直接调用系统调用服务例程。最好的例子就是HTTPD——为了避免上述开销,它从内核中调用套接字和其他系统调用服务例程。Linux系统调用列表进程控制fork创建新进程clone根据指定条件创建子进程execve运行可执行文件exit中止进程_exit立即终止当前进程getdtablesize进程可打开的最大文件数getpgid获取指定进程组标识号setpgid设置指定进程组IDgetpgrp获取当前进程组IDsetpgrp设置当前进程组IDgetpid获取进程IDgetppid获取父进程IDgetpriority获取调度优先级setpriority设置调度优先级modify_ldt读写nanosleep进程本地描述表使进程休眠指定时间nice改变分时进程的优先级pause挂起进程等待信号个性设置进程运行域prctl对进程执行特定操作ptrace进程跟踪sched_get_priority_maxgett静态优先级上限sched_get_priority_min获取静态优先级下限sched_getparam获取进程的调度参数sched_getscheduler获取指定进程的调度策略sched_rr_get_interval获取RR算法调度的实时进程的时间片长度sched_setparam设置进程的调度参数sched_setscheduler设置指定进程的调度策略和参数等待调度队列结束vfork创建子进程执行新程序,经常和execve一起使用wait来等待子进程终止wait3参考waitwaitpid等待指定子进程终止wait4参考waitpidcapget获取进程权限capset设置进程权限getsid获取会话标识号setsid设置会话标识号文件系统控制1.文件读写操作fcntl文件控制打开openfilecreat创建新文件closeclosefiledescriptionwordreadreadfilewritewritefilereadv从文件中读取数据到缓冲区数组writevset将缓冲区数组中的数据写入文件pread随机读取文件pwrite随机写入文件lseek移动filepointer_llseek在64位地址空间移动文件指针dup复制打开的文件描述字dup2根据指定条件复制文件描述字flock添加/解锁pollI/O多路复用truncate截断文件ftruncate见truncateumask设置文件权限掩码fsync将文件在内存中的部分写回磁盘2.文件系统操作access确定文件可访问性chdir更改当前工作目录fchdir请参阅chdirchmod更改文件模式fchmod请参阅chmodchown更改文件所有者或用户组fchown请参阅chownlchown请参阅chownchroot更改根目录stat获取文件状态信息lstat请参阅statfstat请参阅statstatfs获取文件系统信息请参阅statfsreaddir读取目录条目getdents读取目录条目mkdir创建目录mknod创建inodermdir删除目录重命名文件重命名链接创建链接符号链接创建符号链接取消链接删除链接readlink读取符号链接值挂载挂载文件系统umount卸载文件系统ustat获取文件系统信息utime更改文件访问修改时间utimes看到utimequotactlcontroldiskquotasystemcontrolioctlI/Ogeneralcontrolfunction_sysctlread/writesystemparameteracctenableordisableprocessaccountinggetrlimit获取系统资源上限setrlimit设置系统资源上限getrusage获取系统资源使用情况uselib选择二进制函数库使用iopermsetportI/O权限ioplchangeprocessI/Opermissionleveloutblow-levelportoperationrebootrestartswapon打开交换文件和设备swapoff关闭交换文件和设备bdflushcontrolbdflushdaemonsysfs获取核心支持的文件系统类型sysinfogets系统信息adjtimex调整系统时钟alarm设置进程的闹钟getitimer获取定时器值setitimer设置定时器值gettimeofday获取时间和时区settimeofday设置时间和时区stime设置系统日期和时间time获取systemtimetimes获取进程运行时间uname获取名称、版本和主机信息当前UNIX系统的nvhangup挂起当前终端nfsservctl控制NFS守护进程vm86进入模拟8086模式create_module创建可加载模块项delete_module删除可加载模块项init_module初始化模块query_module查询模块信息*get_kernel_syms获取内核符号,已被query_module内存管理brk更改数据段空间sbrk的分配看brkmlock锁定内存页munlock解锁内存页mlockall调用进程锁定所有内存页munlockall调用进程解锁所有内存页mmap映射虚拟内存页munmap移除内存页映射mremap重映射虚拟内存地址msync映射内存地址写入数据回盘mprotect设置内存镜像保护getpagesize获取页面大小sync将内存缓冲区数据写回硬盘cacheflush将指定缓冲区中的内容写回磁盘网络管理getdomainname获取域名setdomainname设置域名gethostid获取主机ID号sethostidsethostIDNo.gethostname获取主机名sethostname设置主机名查看sendrecv通过socket接收信息recvfrom接收UDP信息recvmsgrecvlisten监听socket端口selectpoll多通道同步I/Oshutdown关闭socket上的连接getsockname获取本地socket名称getpeername获取通信伙伴的socket名称getsockoptgetportsettingsetsockoptsetportparametersendfileinfile或者在端口之间传输数据socketpair创建一对连接的匿名socket用户管理getuid获取用户IDsetuid设置用户IDgetgid获取组IDsetgid设置组IDgetegid获取有效组IDsetegid设置有效组IDgeteuid获取有效用户IDseteuid设置有效用户IDsetregid分别设置真实和有效组IDsetreuid分别设置真实和有效用户IDgetresgid分别获取真实,有效和保存的组IDsetresuid设置真实,分别有效和保存的组IDgetresuid分别获取真实、有效和保存的用户IDsetresuid分别设置真实、有效和保存的组IDsetfsgid设置用于文件系统检查的组IDsetfsuid设置用于文件系统检查的用户IDgetgroups获取补充组列表flagssetgroups设置补充组标志列表进程间通信ipc进程间通信的通用控制调用信号sigaction设置指定信号的处理方式sigprocmask根据信号集中的信号进行阻塞/解除阻塞等操作参数sigpending为指定的阻塞信号设置队列sigsuspend暂停进程andwaitforaspecificsignalSignal*sigblock将信号添加到blockedsignalmask,替换为sigprocmask*siggetmask获取现有的blockedsignalmask,替换为sigprocmask*sigsetmaskReplaceexistingblockedsignalmaskwithgivensignalmask,替换为sigprocmask而不是*sigmask,将给定信号转换为掩码。它已被sigprocmask*sigpause取代。它与sigsuspend功能相同,已被sigsuspend取代。它是与BSD兼容的信号处理函数。函数类似于sigactionssetmaskANSIC信号处理函数。sigactionmessagemsgctl消息控制操作msgget获取消息队列msgsnd发送消息msgrcv获取消息pipepipe创建管道信号量semctl信号量控制semget获取一组信号量semop信号量操作共享内存shmctl控制共享内存shmget获取共享内存shmat连接共享内存shmdtteardown共享内存