Feat(process): 增加ProcessGroup以及Session机制 (#1115)

* 添加make run-nographic

* 添加session和processgroup结构体

* 添加一些有关进程组的syscall

* 在fork中加入set_group

* 修改broadcast未实现的信息

* 添加对kill缺失的进程组的逻辑的补充
This commit is contained in:
火花
2025-04-22 13:22:42 +08:00
committed by GitHub
parent 50bbcae01a
commit fcb5bf4496
22 changed files with 1180 additions and 53 deletions

View File

@ -0,0 +1 @@
test-processgroup

View File

@ -0,0 +1,20 @@
ifeq ($(ARCH), x86_64)
CROSS_COMPILE=x86_64-linux-musl-
else ifeq ($(ARCH), riscv64)
CROSS_COMPILE=riscv64-linux-musl-
endif
CC=$(CROSS_COMPILE)gcc
all: main.c
$(CC) -static -o test-processgroup main.c
.PHONY: install clean
install: all
mv test-processgroup $(DADK_CURRENT_BUILD_DIR)/test-processgroup
clean:
rm test-processgroup *.o
fmt:

View File

@ -0,0 +1,87 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define TEST_ASSERT(left, right, success_msg, fail_msg) \
do { \
if ((left) == (right)) { \
printf("[PASS] %s\n", success_msg); \
} else { \
printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n", \
fail_msg, \
(unsigned long)(right), \
(unsigned long)(left)); \
} \
} while (0)
// 打印进程信息
void print_ids(const char *name) {
printf("[%s] PID=%d, PPID=%d, PGID=%d, SID=%d\n",
name,
getpid(),
getppid(),
getpgid(0), // 获取当前进程的 PGID
getsid(0)); // 获取当前进程的 SID
}
int main() {
printf("===== 测试进程组 =====\n");
print_ids("Parent");
// 创建第一个子进程
pid_t child1 = fork();
if (child1 == 0) {
// 子进程1设置自己的进程组
printf("\n[Child1] 子进程启动...\n");
print_ids("Child1 (before setpgid)");
if (setpgid(0, 0) == -1) { // 将自己的 PGID 设置为自己的 PID
perror("setpgid failed");
exit(EXIT_FAILURE);
}
print_ids("Child1 (after setpgid)");
// Assert: PGID 应该等于 PID
// assert(getpgid(0) == getpid());
TEST_ASSERT(getpgid(0), getpid(), "Successfully set child1 as processgroup leader", "Child1 PGID check failed");
sleep(2); // 保持运行,便于观察
exit(EXIT_SUCCESS);
}
// 创建第二个子进程
pid_t child2 = fork();
if (child2 == 0) {
// 子进程2加入第一个子进程的进程组
printf("\n[Child2] 子进程启动...\n");
print_ids("Child2 (before setpgid)");
if (setpgid(0, child1) == -1) { // 将自己的 PGID 设置为 child1 的 PID
perror("setpgid failed");
exit(EXIT_FAILURE);
}
print_ids("Child2 (after setpgid)");
// Assert: PGID 应该等于 child1 的 PID
// assert(getpgid(0) == child1);
TEST_ASSERT(getpgid(0),child1,"Child2 PGID is equal to Child1","Child2 PGID check failed");
sleep(2); // 保持运行,便于观察
exit(EXIT_SUCCESS);
}
// 父进程:等待子进程结束
waitpid(child1, NULL, 0);
waitpid(child2, NULL, 0);
printf("\n[Parent] 所有子进程结束后...\n");
print_ids("Parent");
return 0;
}

1
user/apps/test-session/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
test-session

View File

@ -0,0 +1,20 @@
ifeq ($(ARCH), x86_64)
CROSS_COMPILE=x86_64-linux-musl-
else ifeq ($(ARCH), riscv64)
CROSS_COMPILE=riscv64-linux-musl-
endif
CC=$(CROSS_COMPILE)gcc
all: main.c
$(CC) -static -o test-session main.c
.PHONY: install clean
install: all
mv test-session $(DADK_CURRENT_BUILD_DIR)/test-session
clean:
rm test-session *.o
fmt:

View File

@ -0,0 +1,77 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define TEST_ASSERT(left, right, success_msg, fail_msg) \
do { \
if ((left) == (right)) { \
printf("[PASS] %s\n", success_msg); \
} else { \
printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n", \
fail_msg, \
(unsigned long)(right), \
(unsigned long)(left)); \
} \
} while (0)
#define TEST_CONDITION(condition, success_msg, fail_msg) \
do { \
if (condition) { \
printf("[PASS] %s\n", success_msg); \
} else { \
printf("[FAIL] %s\n", fail_msg); \
} \
} while (0)
// 打印进程信息
void print_ids(const char *name) {
printf("[%s] PID=%d, PPID=%d, PGID=%d, SID=%d\n",
name,
getpid(),
getppid(),
getpgid(0), // 获取当前进程的 PGID
getsid(0)); // 获取当前进程的 SID
}
int main() {
printf("===== 测试 getsid =====\n");
print_ids("Parent");
pid_t child = fork();
if (child == 0) {
// 子进程
printf("\n[Child] 子进程启动...\n");
print_ids("Child (before setsid)");
// 创建新会话
pid_t newsid = setsid();
if (newsid == -1) {
perror("setsid failed");
exit(EXIT_FAILURE);
}
printf("[Child] 创建新会话成功,新 SID = %d\n", newsid);
print_ids("Child (after setsid)");
TEST_ASSERT(newsid, getpid(), "New sid equal to child pid", "failed to set new sid");
TEST_ASSERT(getsid(0), getpid(), "Child sid equal to child pid", "failed to set new sid");
TEST_ASSERT(getpgid(0), getpid(), "Child pgid equal to child pid", "failed to set new sid");
exit(EXIT_SUCCESS);
} else if (child > 0) {
// 父进程
waitpid(child, NULL, 0); // 等待子进程结束
printf("\n[Parent] 子进程结束后...\n");
print_ids("Parent");
TEST_CONDITION(getsid(0)!=child, "Parent sid unchanged", "Parent sid changed");
TEST_CONDITION(getpgid(0)!=child, "Parent pgid unchanged", "Parent pgid changed");
} else {
perror("fork failed");
exit(EXIT_FAILURE);
}
return 0;
}