mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
feat: 实现poll系统调用实现并修复相关bug - 实现poll系统调用,增加对EPollEvent的处理逻辑 - 修复LockedPipeInode中epitems的锁管理问题 - 添加RestartBlock支持,处理系统调用重启逻辑 - 修复EventPoll中epoll_wait的超时处理逻辑 - 新增test_poll测试程序,验证poll功能 Signed-off-by: longjin <longjin@DragonOS.org>
151 lines
4.4 KiB
C
151 lines
4.4 KiB
C
#include <errno.h>
|
||
#include <poll.h>
|
||
#include <pthread.h>
|
||
#include <signal.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <sys/time.h>
|
||
#include <unistd.h>
|
||
|
||
int pipe_fd[2]; // 管道文件描述符数组
|
||
int child_can_exit = 0; // 子进程是否可以退出的标志
|
||
int signal_pid = 0;
|
||
int poll_errno; // poll错误码
|
||
|
||
#define WRITE_WAIT_SEC 3
|
||
#define POLL_TIMEOUT_SEC 5
|
||
#define EXPECTED_MESSAGE "Data is ready!\n"
|
||
#define POLL_DELTA_MS 1000
|
||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||
|
||
// 信号处理函数
|
||
void signal_handler(int signo) {
|
||
printf("[PID: %d, TID: %lu] Signal %d received.\n", getpid(), pthread_self(),
|
||
signo);
|
||
}
|
||
|
||
// 线程函数,用于在n秒后向管道写入数据
|
||
void *writer_thread(void *arg) {
|
||
int seconds = WRITE_WAIT_SEC;
|
||
for (int i = 0; i < seconds; i++) {
|
||
printf("[PID: %d, TID: %lu] Waiting for %d seconds...\n", getpid(),
|
||
pthread_self(), seconds - i);
|
||
sleep(1);
|
||
kill(signal_pid, SIGUSR1); // 发送信号
|
||
}
|
||
const char *message = EXPECTED_MESSAGE;
|
||
write(pipe_fd[1], message, strlen(message)); // 写入管道
|
||
printf("[PID: %d, TID: %lu] Data written to pipe.\n", getpid(),
|
||
pthread_self());
|
||
close(pipe_fd[1]); // 关闭写端
|
||
printf("[PID: %d, TID: %lu] Pipe write end closed.\n", getpid(),
|
||
pthread_self());
|
||
|
||
while (child_can_exit == 0) {
|
||
printf("[PID: %d, TID: %lu] Waiting for main to finish...\n", getpid(),
|
||
pthread_self());
|
||
sleep(1);
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
int main() {
|
||
pthread_t tid;
|
||
struct pollfd fds[1];
|
||
int ret;
|
||
int test_passed = 1; // 假设测试通过
|
||
|
||
// 创建管道
|
||
if (pipe(pipe_fd) == -1) {
|
||
perror("pipe");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
|
||
// 设置信号处理函数
|
||
struct sigaction sa;
|
||
sa.sa_handler = signal_handler;
|
||
sigemptyset(&sa.sa_mask);
|
||
sa.sa_flags = SA_RESTART;
|
||
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
|
||
perror("sigaction");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
|
||
signal_pid = getpid(); // 设置信号接收进程ID
|
||
|
||
// 创建写线程
|
||
if (pthread_create(&tid, NULL, writer_thread, NULL) != 0) {
|
||
perror("pthread_create");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
|
||
// 设置poll监视的文件描述符
|
||
fds[0].fd = pipe_fd[0]; // 监视管道的读端
|
||
fds[0].events = POLLIN; // 监视是否有数据可读
|
||
|
||
printf("[PID: %d, TID: %lu] Waiting for data...\n", getpid(), pthread_self());
|
||
|
||
// 在 poll 调用前后添加时间统计
|
||
struct timeval start_time, end_time;
|
||
gettimeofday(&start_time, NULL); // 记录 poll 开始时间
|
||
|
||
ret = poll(fds, 1, POLL_TIMEOUT_SEC * 1000); // 调用 poll
|
||
poll_errno = errno;
|
||
gettimeofday(&end_time, NULL); // 记录 poll 结束时间
|
||
|
||
// 计算 poll 的总耗时(单位:毫秒)
|
||
long poll_duration_ms = (end_time.tv_sec - start_time.tv_sec) * 1000 +
|
||
(end_time.tv_usec - start_time.tv_usec) / 1000;
|
||
|
||
if (abs((int)poll_duration_ms -
|
||
min(POLL_TIMEOUT_SEC, WRITE_WAIT_SEC) * 1000) >= POLL_DELTA_MS) {
|
||
printf("Poll duration: %ld ms, expected: %d ms, errno: %s\n",
|
||
poll_duration_ms, POLL_TIMEOUT_SEC * 1000, strerror(poll_errno));
|
||
test_passed = 0; // 测试失败(如果 poll 耗时与预期相差较大,认为测试未通过)
|
||
}
|
||
|
||
if (test_passed == 0) {
|
||
|
||
} else if (ret == -1) {
|
||
printf("poll errno: %s\n", strerror(poll_errno));
|
||
test_passed = 0; // 测试失败
|
||
} else if (ret == 0) {
|
||
printf("Timeout! No data available.\n");
|
||
test_passed = 0; // 测试失败
|
||
} else {
|
||
if (fds[0].revents & POLLIN) {
|
||
char buffer[1024];
|
||
ssize_t count = read(pipe_fd[0], buffer, sizeof(buffer)); // 读取数据
|
||
if (count > 0) {
|
||
printf("Data received: %s", buffer);
|
||
// 检查读取的数据是否与预期一致
|
||
if (strcmp(buffer, EXPECTED_MESSAGE) != 0) {
|
||
printf("Unexpected data received.\n");
|
||
test_passed = 0; // 测试失败
|
||
}
|
||
} else {
|
||
printf("No data read from pipe.\n");
|
||
test_passed = 0; // 测试失败
|
||
}
|
||
} else {
|
||
printf("Unexpected event on pipe.\n");
|
||
test_passed = 0; // 测试失败
|
||
}
|
||
}
|
||
|
||
child_can_exit = 1; // 允许子进程退出
|
||
// 等待写线程结束
|
||
pthread_join(tid, NULL);
|
||
close(pipe_fd[0]); // 关闭读端
|
||
|
||
if (test_passed) {
|
||
printf("Test passed!\n");
|
||
} else {
|
||
printf("Test failed!\n");
|
||
}
|
||
|
||
printf("Program finished.\n");
|
||
|
||
return test_passed ? 0 : 1; // 返回0表示测试通过,返回1表示测试失败
|
||
} |