鲲鹏开发板3个openEuler实验
注:难度的取值范围是1-10分,分数越高越难。
I 实验设备
本文3个和openEuler操作系统相关的3个实验将基于“鲲鹏开发板 + VS Code”进行。其中VS Code为系统镜像所自带,而鲲鹏开发板的规格如下所示:

- 产品名称:OrangePi Kunpeng Pro
- 操作系统:openEuler 22.03
- 内存大小:8GB/16GB
- CPU:4核64位ARM处理器,1.6GHz
II 如何登录到开发板

如上图所示,登录到鲲鹏开发板的方式有二:
-
使用PC登录开发板
- PC通过以太网和开发板相连,则:
- 在PC的Console命令行终端中通过
ssh命令登录系统; - 通过VNC(Virtual Network Computing)登录系统✅。
- PC通过串口(Serial)和开发板相连,则:
- 注意设置与鲲鹏开发板串口相同的波特(Baud,symbol/s),这里为115200bps;
- 通过
“MobaXterm”软件选择使用串口(Serial)登录系统。
-
开发板+显示器+键盘+鼠标相连
由于本次实验我们需要登录到开发板上操作系统的桌面以使用VS Code,所以我们选择通过VNC或“开发板+显示器+键盘+鼠标”直连的方式登录。
III 实验准备
登录系统
🔒🗝 安全
为系统安全起见,我们一般以非root用户登录,在这里我们以openEuler用户登录系统,其密码也是“openEuler”。
在运行需要root权限的命令时,要使用sudo命令,例如:
系统会提示输入密码,而输入密码时不会有任何回显。
我们开机并登录到开发板的桌面后如下图所示:

打开 VS Code IDE
现在我们可以以鼠标左键单击“活动”按钮并在弹出来的菜单中单击VS Code(Visual Studio Code)图标以启动这个IDE:

然后我们可以按下“Ctrl+`”(后者和“~”键在一个物理位置上)以打开VS Code里的终端窗口(再次按下这两个键会关闭该窗口):

我们可以在终端窗口里运行以下命令以检查我们的身份:
随后进入到我们的工作目录(这里假设是“~/kdb”,如果没有这个目录可以用mkdir命令创建它):
当要创建一个新的C程序文件的时候可以运行以下命令:
这个命令会创建一个名为“code.c”(这个名称只是一个示例)的文件,并将键盘输入焦点指向它,如果要保存该文件,可以按“Ctrl+s”(如果不保存则不会真正创建该文件)。
💡 扩展知识
在VS Code的编辑窗口中,按下“Ctrl+w”以关闭该编辑窗口,按下“Ctrl+o”用以打开一个文件。
IV 三个实验
现在我们就可以做实验了,本次实验有三,您可以任选一个或几个进行实验。
实验一 获取系统信息
所有的软件都在一定的系统环境上运行,本次实验我们一窥运行在鲲鹏处理器之上的openEuler操作系统的系统环境。
💡 扩展知识
- 鲲鹏处理器是华为基于ARMv8架构开发的通用处理器。作为一款现代处理器,在芯片内部架构中,鲲鹏处理器涉及到了体系结构中的SoC、Chip、DIE、Cluster以及Core等概念,从而组成了一个复杂的综合体。
- openEuler既是一个操作系统,又是一个开源、免费的Linux发行平台,其致力于打造中国原生开源、可自主演进操作系统根社区。作为操作系统,当前openEuler内核源于Linux,支持鲲鹏及其他多种处理器。
我们可以通过Linux shell命令查看系统信息。
快速获取系统基本信息
uname是Linux系统中用于获取系统信息的命令,其名称来源于"Unix Name"。
🎵 代码示例
以上一系列uname命令分别查看了系统的CPU架构、操作系统内核版本及其他信息。
获取CPU详细信息
lscpu是Linux系统中用于显示CPU架构和详细信息的命令。它从“/proc/cpuinfo”文件中提取信息,并以易于阅读的格式展示CPU的相关配置和特性。
🎵 代码示例
其可能的输出是:
查看操作系统版本
🎵 代码示例
可能的显示结果是:
从上面的版本信息“22.03 LTS SP4”可以看出,这是openEuler的一个长期支持版(Long-Term Support),于2022年3月发布,目前已经到了第4个服务包(Service Pack 4)。
进行实验
该实验是编写一个C程序以获取openEuler操作系统上CPU、操作系统的基本信息。
🎵 代码示例
下图显示了运行该程序的一个实例:

🤚 动手操作
请按以下步骤进行实验:
- 进入VS Code终端,在终端中输入以下命令进入“kdb”目录:
cd ~/kdb - 如果不存在此文件夹请输入以下命令创建该文件夹并进入之:
mkdir kdb && cd $_
- 在VS Code中终端创建一个名为“sysinfo.c”的文件:
code sysinfo.c - 现在键盘的输入焦点转到编辑窗口,拷贝上述示例代码并保存该文件
- 在VS Code的终端窗口中编译该文件:
gcc sysinfo.c -o sysinfo - 在VS Code的终端窗口中执行该程式:
./sysinfo - 观察该程式的输出结果。
🔔 清理
记得最后在VS Code终端窗口删除本次实验所有新建文件:rm -f ~/kdb/*
实验二 父子进程关系
fork()是Linux系统编程中非常重要的一个系统调用,用于创建新的进程。
基本概念
功能:fork()用于创建一个与当前进程(父进程)几乎完全相同的子进程。
返回值:
- 成功时:
- 在父进程中返回子进程的PID(进程ID)
- 在子进程中返回0(用于标识自身为子进程)
- 失败时:
关键特性:
- fork() 创建的子进程是父进程的副本,包括:
- 代码段
- 数据段
- 堆栈
- 打开的文件描述符
- 信号处理程序
- 子进程从 fork() 返回处开始执行。
- 父进程可以通过 wait() 或 waitpid() 等待子进程结束。
#### 简单示例
🎵 代码示例
运行上述程序,可能的输出是:
解释:
- 通常每次运行时分配到的进程号都不会相同,所以每次运行的打印结果都会有变化。
- 父进程和子进程的输出顺序不确定(取决于系统调度),但是我们使用了
wait()函数让子进程先输出。 - 父子进程各自拥有变量
mileage的值,说明子进程从父进程拷贝了副本,两者不共享数据。
在VS Code IDE中运行的情况如下图所示:

进行实验
设想一对父子从家中出发到一处风景胜地,父亲立即近路(100公里路程)动身,儿子稍作准备从远路(120公里路程)前往。通常父亲会先到达目的地,但是他会等待儿子到达排在他前面用餐。请用C语言创建父子进程模拟上述情景。
🤚 动手操作
请按以下步骤进行实验:
- 进入VS Code终端,在终端中输入以下命令进入“kdb”目录:
cd ~/kdb - 如果不存在此文件夹请输入以下命令创建该文件夹并进入之:
mkdir kdb && cd $_
- 在VS Code中终端创建一个名为“process.c”的文件:
code process.c - 现在键盘的输入焦点转到编辑窗口,拷贝上述示例代码并保存该文件
- 在VS Code的终端窗口中编译该文件:
gcc process.c -o process - 在VS Code的终端窗口中执行该程式:
./process - 观察该程式的输出结果。
🔔 清理
记得最后在VS Code终端窗口删除本次实验所有新建文件:rm -f ~/kdb/*
实验三 设置CPU亲和性
CPU亲和性(CPU Affinity)是指将进程或线程绑定到特定的CPU核上运行,以优化性能或满足特定需求。通过设置CPU亲和性,可以减少上下文切换和缓存失效,从而提高系统效率。
查看核心数
我们首先需要查看逻辑CPU个数(逻辑CPU个数 = 物理CPU个数 * core个数)。我们可以用以下命令查看:
🎵 代码示例
在本例中,输出为4,表明该硬件系统中共有4个逻辑CPU(从0到3编号)。在本实验中,将通过进程/线程的处理器亲和性将进程/线程绑定到指定的逻辑CPU上。
💡 扩展知识
可通过命令cat /proc/cpuinfo查看更多的处理器信息。
用C函数设置CPU亲和性
在C程式中,我们可以通过sched_setaffinity()函数设置进程的CPU亲和性。
语法:
pid:进程号(Process ID),也就是要进行绑定CPU的进程ID,如果其值为0,则表示指定的是当前进程。 cpusetsize:mask参数所指向的CPU集合的大小。 mask:与进程进行绑定的CPU集合(一个进程可以绑定到多个CPU上运行): - 参数
mask的类型为cpu_set_t,它是一个位图,其中的每个位表示一个CPU核。 - 示例:
- 将
cpu_set_t的第0位设置为1,即0001,表示将进程绑定到CPU0上运行,而不会调度到其他CPU。 - 将
cpu_set_t的第2位设置为1,即0100,表示将进程绑定到CPU2上运行,而不会调度到其他CPU。 - 将
cpu_set_t的第0位和第2位设置为1,即0101,表示将进程绑定到CPU0和CPU2上运行,即进程可能在CPU0或CPU2上运行,而不会在其他CPU上运行。
🎵
*代码示例* 注意这个程序会进入一个无限循环(可以按“Ctrl+c”键终止该循环)。
用Linux命令查看/设置CPU亲和性
具体怎么来查看其运行结果呢?除了利用编程接口来设置CPU亲和性外,在Linux中,我们也可以使用命令行工具taskset来查看和设置。
语法:
pid:进程号,也就是要进行绑定CPU的进程ID。 mask:与进程进行绑定的CPU集合(一个进程可以绑定到多个CPU上运行)。
🎵 代码示例
获取进程号
那么,如何在命令行中得到一个进程的进程号呢——可以使用ps命令。
语法:
- ps(process status,进程状态)命令是Linux系统中用于显示当前进程信息的一个非常有用的工具。
🎵 代码示例
一个实例
下面三个步骤展示了上述诸般操作的一个实例。
🎶步骤 1:首先编辑、编译并执行cpuset.c程序:

🎶步骤 2:然后按下“Ctrl+Shift+`”键开启另外一个终端:

🎶步骤 3:在新的终端里用taskset命令查看/设置CPU亲和性:

🎶步骤 4:最后需要回到上图中右下角子窗口所示的“./cpuset”终端窗口,按下“Ctrl+c”键结束cpuset进程。
进行实验
🤚 动手操作
请按以下步骤进行实验:
- 进入VS Code终端,在终端中输入以下命令进入“kdb”目录:
cd ~/kdb - 如果不存在此文件夹请输入以下命令创建该文件夹并进入之:
mkdir kdb && cd $_
- 在VS Code中终端创建一个名为“cpuset.c”的文件:
code cpuset.c - 现在键盘的输入焦点转到编辑窗口,拷贝上述示例代码并保存该文件
- 在VS Code的终端窗口中编译该文件:
gcc cpuset.c -o cpuset - 在VS Code的终端窗口中执行该程式:
./cpuset - 新启动一个终端;
- 在新的终端中输入以下命令以观察/设置“cpuset”进程的CPU亲和性:
ps -a | grep cpuset # 查看cpuset进程的进程号(比如说是7593) taskset -pc 7593 # 查看该进程的CPU亲和性(进程号7593是一个示例) - taskset -p ❓ 7593 # 请填入正确的掩码,以将该进程绑定在CPU2上
- taskset -pc 7593 # 查看是否绑定成功
- 在运行“cpuset”程式的窗口中按“Ctrl+c”键结束该进程。
🔔 清理
记得最后在VS Code终端窗口删除本次实验所有新建文件:rm -f ~/kdb/*
术语表
本实验中所用术语列表如下:
🏷术语表
- PC
- SSH
- Secure Shell,安全外壳。一种网络安全协议,通过加密和认证机制实现安全的访问和文件传输等业务。
- IDE
- Integrated Development Environment,集成开发环境
- TCP/IP
- Transmission Control Protocol / Internet Protocol,传输控制协议/网际协议。其不仅仅指TCP和IP两个协议,而是一个由ARP(Address Resolution Protocol)、IP、UDP(User Datagram Protocol)、TCP、HTTP(Hypertext Transfer Protocol)、FTP(File Transfer Protocol)、SMTP(Simple Mail Transfer Protocol)、Telnet等协议构成的协议簇,尤其以TCP和IP最具代表性。
附录A 参考文章
🔗登录到鲲鹏开发板的两种方式
🔗如何通过VNC访问鲲鹏开发板
🔗鲲鹏实验平台简介
鲲鹏开发板3个openEuler实验
注:难度的取值范围是1-10分,分数越高越难。
I 实验设备
本文3个和openEuler操作系统相关的3个实验将基于“鲲鹏开发板 + VS Code”进行。其中VS Code为系统镜像所自带,而鲲鹏开发板的规格如下所示:
II 如何登录到开发板
如上图所示,登录到鲲鹏开发板的方式有二:
使用PC登录开发板
ssh命令登录系统;开发板+显示器+键盘+鼠标相连
由于本次实验我们需要登录到开发板上操作系统的桌面以使用VS Code,所以我们选择通过VNC或“开发板+显示器+键盘+鼠标”直连的方式登录。
III 实验准备
登录系统
🔒🗝 安全
为系统安全起见,我们一般以非root用户登录,在这里我们以openEuler用户登录系统,其密码也是“openEuler”。
在运行需要root权限的命令时,要使用
sudo命令,例如:系统会提示输入密码,而输入密码时不会有任何回显。
我们开机并登录到开发板的桌面后如下图所示:
打开 VS Code IDE
现在我们可以以鼠标左键单击“活动”按钮并在弹出来的菜单中单击VS Code(Visual Studio Code)图标以启动这个IDE:
然后我们可以按下“Ctrl+`”(后者和“~”键在一个物理位置上)以打开VS Code里的终端窗口(再次按下这两个键会关闭该窗口):
我们可以在终端窗口里运行以下命令以检查我们的身份:
随后进入到我们的工作目录(这里假设是“~/kdb”,如果没有这个目录可以用
mkdir命令创建它):当要创建一个新的C程序文件的时候可以运行以下命令:
这个命令会创建一个名为“code.c”(这个名称只是一个示例)的文件,并将键盘输入焦点指向它,如果要保存该文件,可以按“Ctrl+s”(如果不保存则不会真正创建该文件)。
💡 扩展知识
在VS Code的编辑窗口中,按下“Ctrl+w”以关闭该编辑窗口,按下“Ctrl+o”用以打开一个文件。
IV 三个实验
现在我们就可以做实验了,本次实验有三,您可以任选一个或几个进行实验。
实验一 获取系统信息
所有的软件都在一定的系统环境上运行,本次实验我们一窥运行在鲲鹏处理器之上的openEuler操作系统的系统环境。
💡 扩展知识
我们可以通过Linux shell命令查看系统信息。
快速获取系统基本信息
uname是Linux系统中用于获取系统信息的命令,其名称来源于"Unix Name"。🎵 代码示例
以上一系列
uname命令分别查看了系统的CPU架构、操作系统内核版本及其他信息。获取CPU详细信息
lscpu是Linux系统中用于显示CPU架构和详细信息的命令。它从“/proc/cpuinfo”文件中提取信息,并以易于阅读的格式展示CPU的相关配置和特性。🎵 代码示例
其可能的输出是:
查看操作系统版本
🎵 代码示例
可能的显示结果是:
从上面的版本信息“22.03 LTS SP4”可以看出,这是openEuler的一个长期支持版(Long-Term Support),于2022年3月发布,目前已经到了第4个服务包(Service Pack 4)。
进行实验
该实验是编写一个C程序以获取openEuler操作系统上CPU、操作系统的基本信息。
🎵 代码示例
/* * sysinfo.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> // 函数声明 void get_cpu_info(); void get_os_info(); int main() { printf("=== CPU 信息 ===\n"); get_cpu_info(); printf("\n=== 操作系统信息 ===\n"); get_os_info(); return 0; } // 获取CPU信息 void get_cpu_info() { FILE *fp; char buffer[128]; // 打开/proc/cpuinfo文件 fp = fopen("/proc/cpuinfo", "r"); if (fp == NULL) { perror("无法打开 /proc/cpuinfo"); exit(EXIT_FAILURE); } // 读取CPU信息 while (fgets(buffer, sizeof(buffer), fp)) { if (strstr(buffer, "CPU architecture")) { printf("处理器架构: ARMv%s", strchr(buffer, ':') + 2); break; } } fclose(fp); } // 获取操作系统信息 void get_os_info() { FILE *fp; char buffer[128]; // 打开/etc/os-release文件 fp = fopen("/etc/os-release", "r"); if (fp == NULL) { perror("无法打开 /etc/os-release"); exit(EXIT_FAILURE); } // 读取操作系统名称 while (fgets(buffer, sizeof(buffer), fp)) { if (strstr(buffer, "PRETTY_NAME")) { printf("操作系统名称: %s", strchr(buffer, '=') + 2); break; } } fclose(fp); // 打开/proc/version文件 fp = fopen("/proc/version", "r"); if (fp == NULL) { perror("无法打开 /proc/version"); exit(EXIT_FAILURE); } // 读取内核版本号 if (fgets(buffer, sizeof(buffer), fp)) { printf("内核版本号: %s", buffer); } fclose(fp); }下图显示了运行该程序的一个实例:
🤚 动手操作
请按以下步骤进行实验:
cd ~/kdbmkdir kdb && cd $_code sysinfo.cgcc sysinfo.c -o sysinfo./sysinfo🔔 清理
记得最后在VS Code终端窗口删除本次实验所有新建文件:
rm -f ~/kdb/*实验二 父子进程关系
fork()是Linux系统编程中非常重要的一个系统调用,用于创建新的进程。
基本概念
功能:fork()用于创建一个与当前进程(父进程)几乎完全相同的子进程。
返回值:
关键特性:
- fork() 创建的子进程是父进程的副本,包括:
- 代码段
- 数据段
- 堆栈
- 打开的文件描述符
- 信号处理程序
- 子进程从 fork() 返回处开始执行。
- 父进程可以通过 wait() 或 waitpid() 等待子进程结束。
#### 简单示例🎵 代码示例
/* * process.c */ #include <stdio.h> #include <unistd.h> #include <sys/wait.h> int main() { int mileage = 0; pid_t pid = fork(); // 创建子进程 if (pid < 0) { // fork 失败 perror("Fork failed"); return 1; } else if (pid == 0) { // 子进程 mileage = 120; printf("\nChild process: PID = %d, Parent PID = %d. \ \n\tAnd the son's journey reached %d kilometers.\n", \ getpid(), getppid(), mileage); } else { // 父进程 mileage = 100; wait(NULL); // 等待子进程结束 printf("\nParent process: PID = %d, Child PID = %d. \ \n\tAnd the father's journey reached %d kilometers.\n", \ getpid(), pid, mileage); } return 0; }运行上述程序,可能的输出是:
Child process: PID = 5026, Parent PID = 5025. And the son's journey reached 120 kilometers. Parent process: PID = 5025, Child PID = 5026. And the father's journey reached 100 kilometers.解释:
wait()函数让子进程先输出。mileage的值,说明子进程从父进程拷贝了副本,两者不共享数据。在VS Code IDE中运行的情况如下图所示:
进行实验
设想一对父子从家中出发到一处风景胜地,父亲立即近路(100公里路程)动身,儿子稍作准备从远路(120公里路程)前往。通常父亲会先到达目的地,但是他会等待儿子到达排在他前面用餐。请用C语言创建父子进程模拟上述情景。
🤚 动手操作
请按以下步骤进行实验:
cd ~/kdbmkdir kdb && cd $_code process.cgcc process.c -o process./process🔔 清理
记得最后在VS Code终端窗口删除本次实验所有新建文件:
rm -f ~/kdb/*实验三 设置CPU亲和性
CPU亲和性(CPU Affinity)是指将进程或线程绑定到特定的CPU核上运行,以优化性能或满足特定需求。通过设置CPU亲和性,可以减少上下文切换和缓存失效,从而提高系统效率。
查看核心数
我们首先需要查看逻辑CPU个数(逻辑CPU个数 = 物理CPU个数 * core个数)。我们可以用以下命令查看:
🎵 代码示例
在本例中,输出为
4,表明该硬件系统中共有4个逻辑CPU(从0到3编号)。在本实验中,将通过进程/线程的处理器亲和性将进程/线程绑定到指定的逻辑CPU上。💡 扩展知识
可通过命令
cat /proc/cpuinfo查看更多的处理器信息。用C函数设置CPU亲和性
在C程式中,我们可以通过
sched_setaffinity()函数设置进程的CPU亲和性。语法:
- 参数
- 示例:
- 将
- 将
- 将
🎵 *代码示例*pid:进程号(Process ID),也就是要进行绑定CPU的进程ID,如果其值为0,则表示指定的是当前进程。cpusetsize:mask参数所指向的CPU集合的大小。mask:与进程进行绑定的CPU集合(一个进程可以绑定到多个CPU上运行):mask的类型为cpu_set_t,它是一个位图,其中的每个位表示一个CPU核。cpu_set_t的第0位设置为1,即0001,表示将进程绑定到CPU0上运行,而不会调度到其他CPU。cpu_set_t的第2位设置为1,即0100,表示将进程绑定到CPU2上运行,而不会调度到其他CPU。cpu_set_t的第0位和第2位设置为1,即0101,表示将进程绑定到CPU0和CPU2上运行,即进程可能在CPU0或CPU2上运行,而不会在其他CPU上运行。/* * cpuset.c */ #define _GNU_SOURCE #include <sched.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> int main(int argc, char **argv) { cpu_set_t mask; CPU_ZERO(&mask); // 初始化CPU集合,将mask置为空 CPU_SET(1, &mask); // 将本进程绑定到CPU1上 // 设置进程的CPU亲和性 if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { printf("Set CPU affinity failed, error: %s\n", strerror(errno)); exit(EXIT_FAILURE); } while (1) {;} // 无限循环,以便实验观察 return 0; }注意这个程序会进入一个无限循环(可以按“Ctrl+c”键终止该循环)。
用Linux命令查看/设置CPU亲和性
具体怎么来查看其运行结果呢?除了利用编程接口来设置CPU亲和性外,在Linux中,我们也可以使用命令行工具
taskset来查看和设置。语法:
pid:进程号,也就是要进行绑定CPU的进程ID。mask:与进程进行绑定的CPU集合(一个进程可以绑定到多个CPU上运行)。🎵 代码示例
获取进程号
那么,如何在命令行中得到一个进程的进程号呢——可以使用
ps命令。语法:
🎵 代码示例
一个实例
下面三个步骤展示了上述诸般操作的一个实例。
🎶步骤 1:首先编辑、编译并执行cpuset.c程序:
🎶步骤 2:然后按下“Ctrl+Shift+`”键开启另外一个终端:
🎶步骤 3:在新的终端里用
taskset命令查看/设置CPU亲和性:🎶步骤 4:最后需要回到上图中右下角子窗口所示的“./cpuset”终端窗口,按下“Ctrl+c”键结束cpuset进程。
进行实验
🤚 动手操作
请按以下步骤进行实验:
cd ~/kdbmkdir kdb && cd $_code cpuset.cgcc cpuset.c -o cpuset./cpusetps -a | grep cpuset # 查看cpuset进程的进程号(比如说是7593)taskset -pc 7593 # 查看该进程的CPU亲和性(进程号7593是一个示例)🔔 清理
记得最后在VS Code终端窗口删除本次实验所有新建文件:
rm -f ~/kdb/*术语表
本实验中所用术语列表如下:
🏷术语表
附录A 参考文章
🔗登录到鲲鹏开发板的两种方式
🔗如何通过VNC访问鲲鹏开发板
🔗鲲鹏实验平台简介