Linux系统调用编程

1. 理解进程和线程的概念。

进程:进程是操作系统进行资源分配和调度的基本单位,通常被视为程序的一个执行实例。每个进程都有自己的地址空间、数据和代码段。一个程序启动时,操作系统会为其创建一个进程,并为其分配资源(如CPU时间、内存等)。进程是相对独立的,在操作系统中,它与其他进程之间的内存是隔离的。

线程:线程是进程中的一个执行单元。一个进程可以拥有多个线程,线程共享同一进程的资源,如内存、文件句柄等。线程间的通信比进程之间更高效,但由于共享资源,它们也更容易产生数据竞争等问题。

1用 ps -a 命令查看系统中各进程的编号 pid

在Linux系统中,可以使用 ps 命令来查看系统中的进程信息。使用 ps -a 命令可以列出当前系统中所有的进程(不包括当前控制终端的进程)。其中,每个进程都有一个唯一的进程ID(PID)。

ps -a

输出的结果会包含进程ID(PID)、进程的终端、状态、启动时间等信息。比如:

PID TTY          TIME CMD
1234 pts/0    00:00:02 bash
2345 pts/0    00:00:01 vim

在这个例子中,12342345 是进程的PID。

2用 kill 命令终止一个进程 PID

kill 命令用于终止一个进程,通常通过PID来指定目标进程。例如,如果你想终止PID为 1234 的进程,可以使用以下命令:

kill 1234

如果进程没有响应,可以强制终止它:

kill -9 1234

kill 命令会发送一个信号给指定的进程,默认情况下是 SIGTERM(终止信号),而 -9SIGKILL 信号,表示强制杀死进程。

2. 解释Linux的“虚拟内存管理”,它与STM32中的真实物理内存(内存映射)有什么区别?

Linux虚拟内存管理: 虚拟内存管理是一种通过将物理内存扩展到磁盘来提高内存使用效率的技术。它使每个进程都认为自己有独立的内存空间,而实际内存(RAM)和磁盘(通常是交换空间或虚拟内存)是通过操作系统的管理机制来协调的。这样,程序可以使用比实际物理内存更多的内存,且操作系统负责将不常用的数据从内存中交换到磁盘上。

Linux使用页表(Page Table)将虚拟地址映射到物理地址。每个进程拥有自己的虚拟地址空间,并且操作系统通过内存管理单元(MMU)和硬件来实现虚拟地址到物理地址的转换。

STM32中的真实物理内存: STM32等嵌入式系统通常没有虚拟内存管理。它们的内存管理较为简单,直接访问物理内存。嵌入式系统通常不使用交换空间,也不支持虚拟内存。所有的内存都是直接映射的,操作系统或固件需要显式管理内存,程序直接通过物理地址进行内存访问。

区别:

  • 虚拟内存(Linux):通过虚拟地址和分页机制,将程序从物理内存的限制中解放出来,可以使用更多的内存,并且支持进程隔离。
  • 真实物理内存(STM32):没有虚拟化机制,程序直接操作物理地址,内存管理较为简单,通常也没有内存保护。

3. 理解Linux系统调用函数 fork()wait()exec() 等的含义和调用方法

fork():fork() 系统调用用于创建一个新的进程,它是通过复制当前进程(父进程)的整个地址空间来实现的。返回值为:

  • 对父进程返回子进程的PID。
  • 对子进程返回0。
#include 
#include 

int main() {
    pid_t pid = fork();
    if (pid == 0) {
        printf("This is the child process\n");
    } else {
        printf("This is the parent process, child PID: %d\n", pid);
    }
    return 0;
}

wait():wait() 系统调用用于让父进程等待子进程的结束,并返回子进程的退出状态。父进程在调用 wait() 时会阻塞,直到某个子进程终止。

#include 
#include 
#include 

int main() {
    pid_t pid = fork();
    if (pid == 0) {
        printf("Child process doing something...\n");
        _exit(0); // Child process exit
    } else {
        wait(NULL); // Parent waits for child process
        printf("Parent process continues after child exits\n");
    }
    return 0;
}

exec():exec() 系列函数(如 execl()execp()execv())用于加载新的程序,并替换当前进程的映像。它们不会返回,如果调用成功,当前进程的映像将被替换为新的程序。exec() 是一个非常重要的系统调用,通常和 fork() 一起使用。

#include 
#include 

int main() {
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程调用exec替换程序
        execl("/bin/ls", "ls", NULL);
    } else {
        // 父进程等待子进程
        wait(NULL);
    }
    return 0;
}
使用vi编辑并编译C代码的步骤

这些步骤将在云服务器或树莓派上运行。

  1. 使用vi创建C源代码文件:

    vi example.c
    

    在编辑器中写入C代码后,保存并退出:按 Esc,然后输入 :wq

  2. 使用gcc编译:

    gcc -o example example.c
    
  3. 运行程序:

    ./example
    

你可能感兴趣的:(linux,运维,服务器)