Technical note
AI system
操作系统的四大模块包括内存管理、进程管理、文件系统管理和输入输出设备管理。每周进行一个CSAPP实验,推荐观看中文视频以节省时间。学习资源包括CSAPP、MIT的操作系统工程和计算机网络课程,以及分布式系统的相关课程。
操作系统:MIT 6.S081: Operating System Engineering
M1: 打印进程树 (pstree)-拉了
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <ctype.h>
#include <string.h>
/* 进程信息结构体:从 /proc/<pid>/status 中提取的三个字段 */
typedef struct{
char name[32]; /* 进程名,来自 status 的 Name: 字段 */
pid_t pid; /* 进程 ID */
pid_t ppid; /* 父进程 ID,来自 status 的 PPid: 字段 */
}proc;
/**
* print_tree - 递归打印进程树(默认模式,不排序)
* @parent_pid: 当前要打印其子进程的父 PID
* @procs: 所有进程信息的数组
* @count: 进程总数
* @level: 当前递归深度(用于缩进)
*
* 遍历全局进程数组,找出 ppid == parent_pid 的所有子进程,
* 按在 /proc 中发现的顺序打印,然后递归到每个子进程。
*/
void print_tree(pid_t parent_pid, proc *procs,int count,int level){
for(int i = 0; i <count;i++){
if(procs[i].ppid == parent_pid){
for(int j = 0; j < level; j++){
printf("--");
}
printf("%s(%d)\n",procs[i].name,procs[i].pid);
print_tree(procs[i].pid,procs,count,level+1);
}
}
}
/* qsort 比较函数:按 pid 升序排列 */
int cmp_pid(const void *a, const void *b) {
const proc *pa = a;
const proc *pb = b;
return pa->pid - pb->pid;
}
/**
* print_tree_s - 递归打印进程树(排序模式)
* @parent_pid: 当前要打印其子进程的父 PID
* @procs: 所有进程信息的数组
* @count: 进程总数
* @level: 当前递归深度(用于缩进)
* @mode: 输出模式:0 = 只显示名字,1 = 显示名字(PID)
*
* 与 print_tree 不同:先收集当前父进程的所有子进程到临时数组,
* 按 pid 排序后再打印,保证同层子进程输出顺序固定。
*/
void print_tree_s(pid_t parent_pid, proc *procs,int count,int level,int mode){
int size_temp = count/2; /* 临时数组上限:一个父进程的子进程数不会超过总进程数的一半 */
proc temp[size_temp];
int idx = 0; /* 实际找到的子进程数 */
for(int i = 0; i <count;i++){
if(procs[i].ppid == parent_pid){
temp[idx++] = procs[i];
}
}
qsort(temp,idx, sizeof(proc), cmp_pid); /* 按 pid 排序当前层 */
if(mode == 0){
for(int i = 0; i < idx; i++){
for(int j = 0; j < level; j++){
printf("--");
}
printf("%s\n",temp[i].name); /* 只输出进程名 */
print_tree_s(temp[i].pid,procs,count,level+1,mode);
}
}
if(mode == 1){
for(int i = 0; i < idx; i++){
for(int j = 0; j < level; j++){
printf("--");
}
printf("%s(%d)\n",temp[i].name,procs[i].pid); /* 输出 名字(PID) */
print_tree_s(temp[i].pid,procs,count,level+1,mode);
}
}
}
int main(int argc, char *argv[]) {
/* 调试输出:打印所有命令行参数(用于开发时确认参数解析) */
for (int i = 0; i < argc; i++) {
assert(argv[i]);
printf("argv[%d] = %s\n", i, argv[i]);
}
assert(!argv[argc]); /* 验证 argv 以 NULL 结尾 */
/* 动态数组:存储所有进程的信息 */
proc *procs = (proc *)malloc(256*sizeof(proc));
int count = 0; /* 已收集的进程数 */
int capacity = 256; /* 当前数组容量 */
/* 遍历 /proc 目录,枚举所有进程 */
DIR *dir = opendir("/proc");
assert(dir);
struct dirent *entry;
if(dir==NULL) { /* opendir 失败时退出(assert 已保证不触发) */
perror("opendir");
exit(EXIT_FAILURE);
}
while ((entry = readdir(dir)) != NULL) {
if(isdigit(entry->d_name[0])) { /* /proc 下数字开头的 entry 即为进程目录 */
count++;
if(count > capacity) { /* 数组扩容(翻倍) */
capacity *= 2;
procs = realloc(procs, capacity * sizeof(proc));
}
/* 构造 /proc/<pid>/status 路径并打开 */
char path[4096];
snprintf(path, sizeof(path), "/proc/%s/status", entry->d_name);
FILE *status_file = fopen(path, "r");
if (status_file) {
char name[32] = {0};
pid_t ppid = -1;
char line[256];
/* 逐行扫描 status 文件,提取 Name 和 PPid */
while (fgets(line, sizeof(line), status_file)) {
if (ppid == -1) sscanf(line, "PPid:\t%d", &ppid); /* 未拿到 PPid 时尝试匹配 */
if (name[0] == '\0') sscanf(line, "Name:\t%31s", name); /* 未拿到 Name 时尝试匹配 */
if (ppid != -1 && name[0] != '\0') break; /* 两个字段都拿到了,提前结束 */
}
/* 填充 proc 结构体 */
procs[count-1].pid = atoi(entry->d_name);
procs[count-1].ppid = ppid;
strncpy(procs[count-1].name, name, 31); /* 复制名字,最多 31 字符 */
procs[count-1].name[31] = '\0'; /* 确保以 \0 结尾 */
fclose(status_file);
}
else {
perror("fopen");
exit(EXIT_FAILURE);
}
}
}
/* 解析命令行参数 —— 线性扫描,设置对应的标志位 */
int show_pid = 0; /* -p / --show-pids:显示 PID */
int numeric_sort = 0; /* -n / --numeric-sort:按 pid 排序输出 */
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--version") == 0) {
printf("老铁666\n");
return 0; /* -V 优先级最高:打印后立即退出 */
}
if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--show-pids") == 0) {
show_pid = 1;
}
if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--numeric-sort") == 0) {
numeric_sort = 1;
}
}
/* 根据标志位组合选择打印策略 */
printf("systemd(1)\n");
if (show_pid && numeric_sort)
print_tree_s(1, procs, count, 1, 1); /* 显示 PID + 排序 */
else if (numeric_sort)
print_tree_s(1, procs, count, 1, 0); /* 排序但不显示 PID */
else if (show_pid)
print_tree(1, procs, count, 1); /* 显示 PID 但不排序 */
else
print_tree(1, procs, count, 1); /* 默认:显示 PID 但不排序 */
closedir(dir);
free(procs);
return 0;
}
计算机网络:USTC Computer Networking:A Top-Down Approach
会有的….
CSAPP-深入理解计算机系统
再说….有点忙
分布式系统: MIT6.824: Distributed System
包学的….