详解Linux的系统调用(下)

一起学嵌入式 2023-12-19 08:48

扫描关注一起学嵌入式,一起学习,一起成长

大家好,今天分享Linux系统调用相关的知识,由于文章篇幅较长,《详解 Linux 的系统调用》分为上下两篇,本文为下篇。

上篇链接:详解 Linux 的系统调用 (上)

1.LINUX系统调用实现

linux系统调用分为3个部分:调用请求 ,响应请求 ,功能实现。

linux系统调用流程图如下:

系统调用提供给应用程序的调用请求接口,调用请求中执行了软中断的指令,应用程序使用调用请求后,处理器会产生一个中断,中断服务得到执行,中断服务根据调用号执行特定的功能实现函数。

2.调用请求

linux系统调用的第一部分是调用请求,调用请求作为系统调用提供给应用程序的接口,在linux系统调用的3部分中,应用程序只有使用调用请求的权限(其它两部分应用程序无法接触到),调用请求需要完成以下两个基本功能:

2.1接口函数

linux系统调用有四种调用请求方式:
1、使用 glibc 库函数。
2、使用 syscall函数。
3、通过linux系统调用宏。
4、使用软中断陷入。

以上这4种方法,每种方法的底层都会用到触发软中断指令。

1、使用 glibc 库函数

glibc是GNU 发布的开源的标准 C 库,glibc 为程序员提供丰富的 API(Application Programming Interface),除了字符串处理、数学运算等用户态服务之外,重要的是封装了操作系统提供的系统服务,即系统调用的封装(本质上还是执行的系统调用)。

系统调用和glibc提供的API的对应关系如下:
情形一:每一个系统调用对应了一个 glibc 库函数,如系统提供的打开文件系统调用 sys_open 对应的是 glibc 中的 open 函数。

情形二:单独的一个glibc 库函数 可能调用多个系统调用,如 glibc 提供的 printf 函数就会调用如 sys_open、sys_mmap、sys_write、sys_close 等等系统调用。

情形三:多个glibc 库函数 也可能只对应同一个系统调用,如glibc 下实现的 malloc、calloc、free 等函数用来分配和释放内存,都利用了内核的 sys_brk 的系统调用。

例如应用程序通过glibc 提供的chmod函数来改变文件的属性,示例代码如下:

#include
int main()
{
    int rc=chmod("./weiwei",0666);
    if(rc==-1)
        perror("chmod fail\n");
    else
        printf("chmod succeed\n");
    return 0;
}

chmod函数用于改变文件weiwei的属性,编译程序得到chmod.o执行文件,运行chmod.o后观察weiwei文件的属性,结果如下:

2、使用 syscall

使用glibc的方法有很多好处,glibc封装了操作系统提供的系统服务,程序员无需知道细节,如 chmod 系统调用号,程序员只需知道 glibc 提供的 API 的原型。其次使用glibc的方法具有更好的移植性,可以很轻松地植到其他平台

任何事物都有两面性,如果 glibc 没有封装某个内核提供的系统调用时,我们就没办法通过使用glibc的方法来调用该系统调用。假设我们自己通过编译内核增加了一个系统调用,这时 glibc 不可能有我们自己新增系统调用的封装 API。

在这种情况下,可以利用 glibc 提供的syscall 库函数直接调用。syscall是一个通过特定子功能号和特定参数调用汇编语言接口的库函数。该函数定义在 unistd.h 头文件中,函数原型如下:

long int syscall (long int sysno, ...)

sysno :为系统调用号,每个系统调用都有唯一的系统调用号来标识。
:可变长的参数,为系统调用所带的参数,不同的系统调用可带0~5个不等的参数。
返回值:该函数返回值为特定系统调用的返回值,如果系统调用失败则返回 -1。

例如应用程序通过 syscall函数来改变文件的属性,示例代码如下:

#include
#include
//syscall接口函数声明在头文件unistd.h中
#include
//SYS_chmod在头文件syscall.h中
int main()
{
    int rc=syscall(SYS_chmod,"./weiwei",0777);
    if(rc==-1)
        perror("SYS_chmod chmod fail\n");
    else
        printf("SYS_chmod chmod succeed\n");
    return 0;
}

syscall(SYS_chmod,“./weiwei”,0777)函数用于改变文件weiwei的属性,编译得到syschmod.o执行文件,运行syschmod.o后观察weiwei文件的属性,结果如下:

3、通过_syscall系统调用宏

Linux内核提供了一组宏,用于实现系统调用接口函数,实现系统调用后应用程序就可以使用该系统调用。这组宏是_syscalln(),其中n的范围从0到6,这组宏会设置好寄存器并调用软中断指令,_syscalln()宏如下:

_syscall0(),_syscall1(),_syscall2(),_syscall3(),_syscall4(),_syscall5(),_syscall6()。

宏名称字符串“syscall0”中的0表示无参数,“syscall1”中的1表示带1个参数,“syscall2”中的2表示带2个参数。如果系统调用带有1个参数,那么就应该使用宏_syscall1()。

以_syscall0()为例,_syscall0()为不带参数的系统调用宏函数,它以嵌入汇编的形式调用软中断指令int 0x80。

#define _syscall0(type,name) \
type name(void) \
 { \
 long __res; \
 __asm__ volatile ("int $0x80" \          // 调用系统中断0x80。
         : "=a" (__res) \                 // 返回值eax(__res)。
         : "0" (__NR_##name)); \          // 输入为系统中断调用号__NR_name。
 if (__res >= 0) \                        // 如果返回值>=0,则直接返回该值。
         return (type) __res; \
 errno = -__res; \                        // 否则置出错号,并返回-1。
 return -1; \
 }

假设我们要新增一个名为test系统调用,我们可以使用_syscall系统调用宏实现,假设test系统调用参数个数为0个,我们通过_syscall0(int, test)申请了一个新的系统调用。

我们通过_syscall0(int, test)声明一个系统调用,根据宏定义我们把_syscall0(int, test)这个宏展开并替代得到如下语句:

static inline int test(void)
{
long __res;

__asm__ volatile ("int $0x80" : "=a" (__res) : "0" (__NR_test));
if (__res >= 0)
        return (int) __res;
errno = -__res;
return -1;
}

_syscall0(int, test)实际上是声明了一个名为test的函数,声明函数后,应用程序就可以使用test这个系统调用了(当然还有内核相关代码需要实现),test系统调用示例代码如下:

#include
#include
//syscall接口函数声明在头文件unistd.h中
#include
//SYS_chmod在头文件syscall.h中
_syscall0(int, test);
int main()
{
    int rc=test();
    if(rc==-1)
        perror("test fail\n");
    else
        printf("test succeed\n");
    return 0;
}

4、通过软中断指令陷入

用户态程序通过软中断指令int 0x80 来陷入内核态,通过寄存器传递参数,eax 传递的是系统调用号,ebx、ecx、edx、esi和edi 来依次传递参数,当系统调用返回值存放在 eax 中。

以调用chmod修改文件属性为例,系统调用通过内联汇编实现,示例代码如下:

#include 
#include 
#include 
//SYS_chmod在头文件syscall.h中
#include 

int main()
{
    long rc;
    unsigned short mode = 0777;     
    char *file_name = "./weiwei";
 /*内联汇编 软中断指令 */
    asm(
            "int $0x80"
            : "=a" (rc)
            : "0" (SYS_chmod), "b" ((long)file_name), "c" ((long)mode)
    );     
    if (rc == -1)
       perror("SYS_chmod chmod fail\n");
    else
        printf("SYS_chmod chmod succeed\n");
    return 0;
}

2.2触发软中断

以上这4种方法,每种方法的底层都会用到触发软中断指令。系统调用的参数 由各通用寄存器传递,然后执行软中断指令(INT 0x80) ,处理器响应中断并开始执行中断服务程序,此时处理器模式变为特权模式。我们以glibc-2.23中的X86体系为例,下面分别讲述4中方法如何调用软中断指令。

1、glibc 库函数

glibc-2.23\sysdeps\unix\sysv\linux\generic中有chmod函数的定义,代码如下:

#include 
#include 
#include 
#include 
#include 

/* Change the protections of FILE to MODE.  */
int
__chmod (const char *file, mode_t mode)
{
  return INLINE_SYSCALL (fchmodat, 3, AT_FDCWD, file, mode);
}
weak_alias (__chmod, chmod)

INLINE_SYSCALL 宏在glibc-2.23\glibc-2.23\sysdeps\i386\sysdep.h中定义,代码如下:

# define INLINE_SYSCALL(name, nr, args...) \

  ({               \
    unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);       \
    __glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))        \
    ? __syscall_error (-INTERNAL_SYSCALL_ERRNO (resultvar, ))        \
    : (int) resultvar; })

INTERNAL_SYSCALL 宏在glibc-2.23\glibc-2.23\sysdeps\i386\sysdep.h中定义,代码如下:

#define INTERNAL_SYSCALL(name, err, nr, args...) \
  ({               \
    register unsigned int resultvar;           \
    INTERNAL_SYSCALL_MAIN_##nr (name, err, args);         \
    (int) resultvar; })

INTERNAL_SYSCALL_MAIN_##nr宏的几种形式在glibc-2.23\glibc-2.23\sysdeps\i386\sysdep.h中定义如下:

#define INTERNAL_SYSCALL_MAIN_0(name, err, args...) \
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 0, args)
#define INTERNAL_SYSCALL_MAIN_1(name, err, args...) \
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 1, args)
#define INTERNAL_SYSCALL_MAIN_2(name, err, args...) \
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 2, args)
#define INTERNAL_SYSCALL_MAIN_3(name, err, args...) \
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 3, args)
#define INTERNAL_SYSCALL_MAIN_4(name, err, args...) \
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 4, args)
#define INTERNAL_SYSCALL_MAIN_5(name, err, args...) \
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 5, args)

INTERNAL_SYSCALL_MAIN_INLINE宏在glibc-2.23\glibc-2.23\sysdeps\i386\sysdep.h中定义,代码如下:

#  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \

    LOADREGS_##nr(args)       \
    asm volatile (       \
    "int $0x80"        \
    : "=a" (resultvar)       \
    : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")

chmod库函数的定义最终通过int $0x80 触发软中断。

2、 syscall函数

glibc-2.23\glibc-2.23\sysdeps\unix\sysv\linux\hppa\syscall.c中的syscall函数定义如下:

long int
syscall (long int __sysno, ...)
{
  /* FIXME: Keep this matching INLINE_SYSCALL for hppa */
  va_list args;
  long int arg0, arg1, arg2, arg3, arg4, arg5;
  long int __sys_res;

  /* Load varargs */
  va_start (args, __sysno);
  arg0 = va_arg (args, long int);
  arg1 = va_arg (args, long int);
  arg2 = va_arg (args, long int);
  arg3 = va_arg (args, long int);
  arg4 = va_arg (args, long int);
  arg5 = va_arg (args, long int);
  va_end (args);

  {
    LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5)
    register unsigned long int __res asm("r28");
    PIC_REG_DEF
    LOAD_REGS_6
    asm volatile (SAVE_ASM_PIC
    " ble  0x100(%%sr2, %%r0) \n"
    " copy %1, %%r20  \n"
    LOAD_ASM_PIC
    : "=r" (__res)
    : "r" (__sysno) PIC_REG_USE ASM_ARGS_6
    : "memory", CALL_CLOB_REGS CLOB_ARGS_6);
    __sys_res = __res;
  }
  if ((unsigned long int) __sys_res >= (unsigned long int) -4095)
    {
      __set_errno (-__sys_res);
      __sys_res = -1;
    }
  return __sys_res;
}

在syscall 函数中使用嵌入汇编的形式调用软中断指令。

3、_syscall系统调用宏

以_syscall0()为例,它以嵌入汇编的形式调用软中断指令int 0x80

4、通过软中断指令陷入

使用软中断陷入是直接使用汇编指令int $0x80 触发软中断

3.响应请求

软中断是通过一条具体指令SWI,当CPU执行到SWI指令时会触发中断,进入中断程序。以X86 体系架构为例,软件中断指令( int 0x80)用于产生软中断,同时处理器从用户模式变换到特权模式。

应用程序调用系统调用接口函数后,底层会执行软中断指令( int 0x80 ),处理器就从用户态切换到内核态,并跳转到了 0x80 中断向量号 ,对应的中断向量服务程序 ,并根据传入的调用号执行相应的系统服务函数,中断触发后的响应流程如下图:

\linux-2.6.28.6\arch\x86\include\asm\irq_vectors.h中SYSCALL_VECTOR宏如下:

# define SYSCALL_VECTOR  0x80

linux-2.6.28.6\arch\x86\kernel\traps.c 中断配置如下:

void __init trap_init(void)
{
 .....省略代码.....
 set_intr_gate(0, ÷_error);
 set_intr_gate_ist(1, &debug, DEBUG_STACK);
 set_intr_gate_ist(2, &nmi, NMI_STACK);
 /* int3 can be called from all */
 set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
 /* int4 can be called from all */
 set_system_intr_gate(4, &overflow);
 set_intr_gate(5, &bounds);
 set_intr_gate(6, &invalid_op);
 set_intr_gate(7, &device_not_available);
 .....省略代码.....
 set_system_trap_gate(SYSCALL_VECTOR, &system_call);
 .....省略代码.....
}

0x80 中断向量服务入口为system_call,system_call函数定义在linux-2.6.28.6/arch/x86/kernel/ entry_32.S中ENTRY(system_call),system_call汇编代码涉较多,下面的代码保留了最核心部分代码:

ENTRY(system_call)
 RING0_INT_FRAME   # can't unwind into user space anyway
 pushl %eax   # save orig_eax
 CFI_ADJUST_CFA_OFFSET 4
 SAVE_ALL
 GET_THREAD_INFO(%ebp)
     # system call tracing in operation / emulation
 /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
 testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
 jnz syscall_trace_entry
 cmpl $(nr_syscalls), %eax
 jae syscall_badsys
syscall_call:
 call *sys_call_table(,%eax,4)
 movl %eax,PT_EAX(%esp)  # store the return value
  .....省略代码.....
ENDPROC(system_call)

我们将以上简化的代码根据syscall_call标号分为两部分:syscall_call准备,syscall_call调用

syscall_call准备
SAVE_ALL 的主要工作就是将 gs、fs、es、ds、eax、ebp 等寄存器中的值在调用系统调用服务程序之前将其压入到内核栈中保存。

cmpl $(nr_syscalls), %eax 指令语句则是用来判断从用户态传入的系统调用号是否大于系统中所实现的最大的系统调用编号,判断传入的系统调用编号是否合法,如果不合法程序就跳转到 syscall_badsys 处执行相应的出错处理程序。

syscall_call调用
syscall_call中的工作就是就是去调用与传入系统调用号对应的系统调用服务程序,而这一步中就只有一条非常简单的 call 指令语句,如下所示:

call *sys_call_table(,%eax,4)

call *sys_call_table(,%eax,4) 根据 eax 中传入的系统调用号来调用对应的系统调用服务程序, sys_call_table是一个函数指针数组(跳转表)。

sys_call_table跳转表

sys_call_table定义如下:

/* 代码文件路径:/linux-2.6.28.6/arch/x86/kernel/syscall_32.c */
#undef __SYSCALL
#define __SYSCALL(nr, sym) [nr] = sym,
#undef _ASM_X86_UNISTD_64_H

typedef void (*sys_call_ptr_t)(void);

extern void sys_ni_syscall(void);

const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
 /*
 *Smells like a like a compiler bug -- it doesn't work
 *when the & below is removed.
 */
 [0 ... __NR_syscall_max] = &sys_ni_syscall,
#include 
};

sys_call_table 是函数指针类型的的数组,数组长度就是系统中所包含的全部系统调用的数量__NR_syscall_max + 1,[0 … __NR_syscall_max] = &sys_ni_syscall代码完成的就是对数组元素初始化的工作, #include 是直接将头文件中的内容在数组中展开。

asm/unistd_64.h文件内容如下:

#ifndef _ASM_X86_UNISTD_64_H
#define _ASM_X86_UNISTD_64_H

#ifndef __SYSCALL
#define __SYSCALL(a, b)
#endif


/* at least 8 syscall per cacheline */
#define __NR_read    0

__SYSCALL(__NR_read, sys_read)
#define __NR_write    1
__SYSCALL(__NR_write, sys_write)
#define __NR_open    2

__SYSCALL(__NR_open, sys_open)
#define __NR_close    3
__SYSCALL(__NR_close, sys_close)
#define __NR_stat    4

__SYSCALL(__NR_stat, sys_newstat)
#define __NR_fstat    5
__SYSCALL(__NR_fstat, sys_newfstat)
#define __NR_lstat    6

__SYSCALL(__NR_lstat, sys_newlstat)
#define __NR_poll    7
__SYSCALL(__NR_poll, sys_poll)

  .....省略代码.....

sys_call_table扩展开后为:

__visible const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
    [0 ] = sys_read,
    [1] = sys_write
    [2] = sys_open,
 [3] = sys_close,
  .....省略代码.....
};

sys_call_table[0] 就是执行sys_read函数,使用跳转表后程序的执行状态如下图:

4.功能实现

系统调用号和系统调用服务程序是一一对应关系,一个系统调用对应一个系统调用服务程序。90号系统调用对应的系统调用服务程序就是 sys_chmod,如下所示:

#define __NR_chmod    90
__SYSCALL(__NR_chmod, sys_chmod)

sys_chmod函数定义如下:

linux-2.6.28.6\linux-2.6.28.6\fs\open.c 
SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode)
{
 return sys_fchmodat(AT_FDCWD, filename, mode);
}

为什么不是 sys_chmod() 作为函数名呢?Linux 系统中的系统调用服务函数都是使用 SYSCALL_DEFINEx (0,1,2,3,4,5,6) 宏来实现的,这样使得用户态和内核态的两个函数“看起来一样”。

SYSCALL_DEFINEx 的定义如下所示,

/* 代码文件路径:/linux-3.18.6/include/linux/syscalls.h */
#define SYSCALL_METADATA(sname, nb, ...)


#define SYSCALL_DEFINE0(sname)                  \
    SYSCALL_METADATA(_##sname, 0);              \
    asmlinkage long sys_##sname(void)

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
#define SYSCALL_DEFINEx(x, sname, ...)              \
    SYSCALL_METADATA(sname, x, __VA_ARGS__)         \
    __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)

#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
#define __SYSCALL_DEFINEx(x, name, ...)                 \
    asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))   \
        __attribute__((alias(__stringify(SyS##name))));     \

所以根据上面的定义,宏 SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode)展开后得到的结果就是:

asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
{
 return sys_fchmodat(AT_FDCWD, filename, mode);

5.自定义一个系统调用

通常情况下已有的系统调用可以满足我们绝大多少需求,但是在极少数情况下,我们需要额外增加一个自定义的系统调用。接下来我们来学习一下如何增加一个自定义系统调用。例如我们自定义一个名为weiweicall的系统调用(该系统调用的参数为0)。

一旦系统调用的名字确定下来了,那么在系统调用中的几个相关名字也就确定下来了。
调用接口函数:weiweicall
系统调用的编号名字:__NR_weiweicall
内核中系统调用的实现程序的名字:sys_weiweicall

5.1接口函数

在前面我们描述了4种系统调用的接口,我们可以使用linux系统调用宏_syscall0来定义一个可以产生软中断的函数:

#include 
_syscall0(int,weiweicall) /* 注意这里没有分号*/
int main()
{
 weiweicall();
}

定义了weiweicall用户系统调用函数,接下来我们定义系统调用号。

5.2添加系统调用号

我们要做的就是在文件asm/unistd_64.h文中添加自定义的系统调用号__NR_weiweicall,代码如下:

linux-2.6.28.6\arch\x86\include\asm\unistd_64.h

#define __NR_eventfd2    290

__SYSCALL(__NR_eventfd2, sys_eventfd2)
#define __NR_epoll_create1   291
__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
#define __NR_dup3    292

__SYSCALL(__NR_dup3, sys_dup3)
#define __NR_pipe2    293
__SYSCALL(__NR_pipe2, sys_pipe2)
#define __NR_inotify_init1   294

__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
//增加自定义系统调用
#define __NR_weiweicall   295
__SYSCALL(__NR_weiweicall, sys_weiweicall)

添加系统调用号之后,系统才能根据这个号作为索引,去找syscall_table中的相应表项。目前系统已经能够正确地找到并且调用sys_mysyscall。剩下事情的就只剩下sys_mysyscall内核函数的实现。

5.3sys_mysyscall 的实现

我们自定义的程序添加在内核代码中,如kernel/sys.c 里面,我们没有在kernel 目录下另外 添加自己的一个文件,这样做的不用修改Makefile,可以直接编译。我们可以用宏实现功能函数,也可以直接定义实现功能函数:

//直接定义sys_xxx函数
asmlinkage int sys_weiweicall(void)
{
 printk( "weiwei  system call!");
 return 1;
}
//使用SYSCALL_DEFINE定义函数
SYSCALL_DEFINE0(weiweicall)
{
 printk( "weiwei  system call!");
 return 1;
}

编译内核后,应用程序就可以使用weiweicall系统调用。

#include 
_syscall0(int,weiweicall) /* 注意这里没有分号*/
int main()
{
 weiweicall();
}

6.系统调用分类

系统调⽤按照功能逻辑⼤致可分为“进程控制”、“⽂件系统控制”、“系统控制”、“存管管理”、“⽹络管理”、“socket控制”、“⽤户管理”、“进程间通信”。

进程控制类系统调用

fork,clone,execve,exit,_exit,getdtablesize,getpgid,setpgid,getpgrp,setpgrp,getpid,getppid,getpriority,setpriority,modify_ldt,nanosleep,nice,pause,personality,prctl,ptrace,sched_get_priority_max,sched_get_priority_min,sched_getparam,sched_getscheduler,sched_rr_get_interval,sched_setparam,sched_setscheduler,sched_yield,vfork,wait,wait3,waitpid,wait4,capget,capset,getsid,setsid

文件操作类系统调用

fcntl,open,creat,close,read,write,readv,writev,pread,pwrite,lseek,_llseek,dup,dup2,flock,polltruncate,ftruncate,umask,fsync

文件系统操作类系统调用

access,chdir,fchdir,chmod,fchmod,chown,fchown,lchown,chroot,stat,lstat,fstat,statfs,fstatfs,readdir,getdents,mkdir,mknod,rmdir,rename,link,symlink,unlink,readlink,mount,umount,ustat,utime,utimes,quotactl

系统控制类系统调用

ioctl,_sysctl,acct,getrlimit,setrlimit,getrusage,uselib,ioperm,iopl,outb,reboot,swapon,swapoff,bdflush,sysfs,sysinfo,adjtimex,alarm,getitimer,setitimer,gettimeofday,settimeofday,stime,time,times,uname,vhangup,nfsservctl,vm86,create_module,delete_module,init_modulequery_module,get_kernel_syms

内存管理类系统调用

brk,sbrk,mlock,munlock,mlockall,munlockall,mmap,munmap,mremap,msync,mprotect,getpagesize,sync,cacheflush

网络管理类系统调用

getdomainname,setdomainname,gethostid,sethostid,gethostname,sethostname,socketcall,socket,bind,connect,accept,send,sendto,sendmsg,recv,recvfrom,recvmsg,listen,select,shutdown,getsockname,getpeername,getsockopt,setsockopt,sendfile,socketpair

用户管理类系统调用

getuid,setuid,getgid,setgid,getegid,setegid,geteuid,seteuid,setregid,setreuid,getresgid,setresgid,getresuid,setresuid,setfsgid,setfsuid,getgroups,setgroups

进程间通信类系统调用

sigaction,sigprocmask,sigpending,sigsuspend,signal,kill,sigblock,siggetmask,sigsetmask,sigmask,sigpause,sigvec,ssetmask,msgctl,msgget,msgsnd,msgrcv,pipe ,semctl,semget,semop,shmctl,shmget,shmat,shmdt

总结:系统调用使用接口函数产生软中断,处理器进入中断状态执行相应的功能程序。

原文:https://blog.csdn.net/li_man_man_man/article/details/124599825

文章来源于网络,版权归原作者所有,如有侵权,请联系删除。



关注【一起学嵌入式】,回复加群进技术交流群。



觉得文章不错,点击“分享”、“”、“在看” 呗!

一起学嵌入式 公众号【一起学嵌入式】,RTOS、Linux编程、C/C++,以及经验分享、行业资讯、物联网等技术知
评论
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 79浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 97浏览
  • 在当前人工智能(AI)与物联网(IoT)的快速发展趋势下,各行各业的数字转型与自动化进程正以惊人的速度持续进行。如今企业在设计与营运技术系统时所面临的挑战不仅是技术本身,更包含硬件设施、第三方软件及配件等复杂的外部因素。然而这些系统往往讲究更精密的设计与高稳定性,哪怕是任何一个小小的问题,都可能对整体业务运作造成严重影响。 POS应用环境与客户需求以本次分享的客户个案为例,该客户是一家全球领先的信息技术服务与数字解决方案提供商,遭遇到一个由他们所开发的POS机(Point of Sal
    百佳泰测试实验室 2025-01-09 17:35 99浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 111浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 96浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 113浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 88浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 93浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 95浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 84浏览
  • 职场是人生的重要战场,既是谋生之地,也是实现个人价值的平台。然而,有些思维方式却会悄无声息地拖住你的后腿,让你原地踏步甚至退步。今天,我们就来聊聊职场中最忌讳的五种思维方式,看看自己有没有中招。1. 固步自封的思维在职场中,最可怕的事情莫过于自满于现状,拒绝学习和改变。世界在不断变化,行业的趋势、技术的革新都在要求我们与时俱进。如果你总觉得自己的方法最优,或者害怕尝试新事物,那就很容易被淘汰。与其等待机会找上门,不如主动出击,保持学习和探索的心态。加入优思学院,可以帮助你快速提升自己,与行业前沿
    优思学院 2025-01-09 15:48 98浏览
  • HDMI 2.2 规格将至,开启视听新境界2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新HDMI规范为规模庞大的 HDMI 生态系统带来更多选择,为创建、分发和体验理想的终端用户效果提供更先进的解决方案。新技术为电视、电影和游戏工作室等内容制作商在当前和未来提供更高质量的选择,同时实现多种分发平台。96Gbps的更高带宽和新一代 HDMI 固定比率速率传输(Fixed Rate Link)技术为各种设备应用提供更优质的音频和视频。终端用户显示器能以最
    百佳泰测试实验室 2025-01-09 17:33 106浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦