ctrl+z 到底做了什么?

本文介绍了命令行中Ctrl+C和Ctrl+Z的区别。以往以为两者无区别,在执行带界面程序时发现不同,Ctrl+C可直接终止程序,Ctrl+Z会使页面卡死。还介绍了Ctrl+Z挂起进程后相关操作,如jobs显示暂停进程、bg和fg让进程在后台或前台运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以前,在命令行执行程序的时候,终止执行ctrl+c,如果Ctrl+c失效了,一般都会使用ctrl+z,将当前卡死或者无响应的终端释放出来,却一直没有探究到底为什么,甚至以为这两种命令操作无区别。其实不然。
发现不同是当在命令行执行一个带界面的程序时,ctrl+c可以直接终止了程序,界面直接消失,但ctrl+z则不然,页面卡死,无法接受信号,频繁点击导致“程序无响应,强制关闭”弹窗。所以才研究这两种命令的区别。

(1) CTRL+Z挂起进程并放入后台
(2) jobs 显示当前暂停的进程
(3) bg %N 使第N个任务在后台运行(%前有空格)
(4) fg %N 使第N个任务在前台运行
默认bg,fg不带%N时表示对最后一个进程操作!
参考自:https://www.cnblogs.com/pcy0/p/4177274.html

才恍然大悟,好像这些年的知识都白学了,太基础的反而不扎实。另外,注意在挂起时进程是可以接受消息的,当恢复运行(bg或者fg)后,各种消息都会顺序执行。

<think>我们保留了匿名管道通信,并且添加了信号处理功能(SIGINT和SIGTSTP)来支持Ctrl+C(中断)和Ctrl+Z(挂起)的功能。为了测试这些功能,我们可以按照以下步骤进行: 1. **编译并运行Shell程序**:将上述代码保存为`mysh.c`,然后使用gcc编译(例如:`gcc mysh.c -o mysh`),然后运行`./mysh`。 2. **测试Ctrl+C(中断信号)**: - 在Shell提示符下,运行一个长时间运行的前台命令,例如`sleep 100`。 - 在命令执行过程中,按下Ctrl+C。 - 预期结果:命令被中断,Shell打印出新的提示符。 3. **测试Ctrl+Z(挂起信号)**: - 在Shell提示符下,运行一个长时间运行的前台命令,例如`sleep 100`。 - 在命令执行过程中,按下Ctrl+Z。 - 预期结果:命令被挂起(停止),Shell打印出类似`[pid] stopped`的信息,并回到提示符状态。然后你可以使用`jobs`命令查看停止的任务,并使用`fg`命令将其转为前台继续运行。 4. **测试后台任务的信号处理**: - 启动一个后台任务,例如`sleep 200 &`。 - 使用`jobs`命令查看其状态,应为运行中(Running)。 - 向该后台任务发送SIGINT信号(使用`kill -SIGINT <pid>`)或SIGTSTP信号(使用`kill -SIGTSTP <pid>`),然后使用`jobs`命令观察状态变化。 5. **测试管道通信**: - 运行一个需要管道通信的命令,例如`echo "Hello, World!"`,观察输出是否正确。 - 运行一个会输出较多内容的命令(例如`ls -l /`),观察输出是否被正确捕获并显示。 注意:在测试Ctrl+C和Ctrl+Z时,确保你是在前台进程运行期间按下这些组合键。另外,我们的信号处理函数中,Ctrl+C(SIGINT)会发送给前台进程组,而Ctrl+Z(SIGTSTP)会挂起前台进程。 代码中我们已经设置了信号处理函数: - `sigint_handler` 处理SIGINT(Ctrl+C) - `sigtstp_handler` 处理SIGTSTP(Ctrl+Z) - `sigchld_handler` 处理SIGCHLD(子进程状态变化) 因此,在运行程序后,你可以按照上述步骤测试。 另外,注意我们的后台任务在运行时会将其输出重定向到`/dev/null`,所以你不会在终端上看到后台任务的输出。但前台命令的输出会通过管道被父进程读取并打印。 如果你在测试过程中遇到问题,例如信号没有按预期工作,请检查终端设置(例如是否禁用了某些信号)以及代码是否正确编译运行。 下面再次提供完整的代码(已包含上述所有功能)以供使用:</think>### 在保留匿名管道通信的程序中测试Ctrl+Z和Ctrl+C功能 在改进后的Shell程序中,已经实现了对Ctrl+Z(SIGTSTP)和Ctrl+C(SIGINT)信号的处理功能。以下是详细的测试方法和步骤: #### 测试步骤: 1. **编译并运行程序**: ```bash gcc mysh.c -o mysh ./mysh ``` 2. **测试Ctrl+C(中断进程)**: ```bash mysh> sleep 60 # 启动一个长时间运行的前台进程 # 等待几秒后按下 Ctrl+C ``` **预期结果**: - 进程立即终止 - 显示新提示符 `mysh>` 3. **测试Ctrl+Z(挂起进程)**: ```bash mysh> sleep 60 # 启动前台进程 # 等待几秒后按下 Ctrl+Z ``` **预期结果**: - 显示 `[pid] stopped`(如 `[12345] stopped`) - 进程转为后台停止状态 - 可通过 `jobs` 命令查看状态 4. **测试管道通信中的信号处理**: ```bash mysh> find / -name "*.txt" # 会产生大量输出的命令 # 在输出过程中按下 Ctrl+C/Ctrl+Z ``` **预期结果**: - 命令立即停止,管道正确关闭 - 无残留进程或文件描述符泄漏 5. **恢复挂起的进程**: ```bash mysh> jobs # 查看停止的进程ID [1] 12345 sleep 60 (Stopped) mysh> fg 1 # 将任务转为前台 # 此时可继续测试Ctrl+C终止 ``` #### 关键代码实现说明: 1. **信号处理器注册**: ```c signal(SIGINT, sigint_handler); // Ctrl+C signal(SIGTSTP, sigtstp_handler); // Ctrl+Z ``` 2. **Ctrl+C处理逻辑**: ```c void sigint_handler(int sig) { if (foreground_pid != 0) { kill(foreground_pid, SIGINT); // 发送给整个进程组 printf("\n"); } } ``` 3. **Ctrl+Z处理逻辑**: ```c void sigtstp_handler(int sig) { if (foreground_pid != 0) { kill(foreground_pid, SIGTSTP); printf("\n[%d] stopped\n", foreground_pid); foreground_pid = 0; // 重置前台PID } } ``` 4. **管道安全关闭**: ```c // 父进程读取管道数据 while ((count = read(pipefd[0], buffer, sizeof(buffer)-1)) > 0) { buffer[count] = '\0'; printf("%s", buffer); } close(pipefd[0]); // 确保关闭管道 ``` #### 测试验证要点: 1. **管道完整性**: - 信号中断后无数据丢失或损坏 - 使用 `echo "Test" | ./mysh` 验证管道输入 2. **进程状态管理**: - 使用 `ps aux | grep sleep` 检查进程是否完全终止 - 验证 `jobs` 命令显示的进程状态准确性 3. **资源回收**: - 信号处理后无僵尸进程(通过 `ps -ef | grep defunct` 检查) - 使用 `lsof -p [pid]` 验证文件描述符正确关闭 > 测试时注意:后台进程的输出已被重定向到 `/dev/null`,因此只有前台进程会通过管道输出到终端[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值