Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊!
喜欢我的博客的话,记得点个红心❤️和小关小注哦!您的支持是我创作的动力!数据源
存放在我的资源下载区啦!
Linux程序开发(七):alarm /setitimer 编写文字时钟程序
1. 问答题
1.1. 简述什么是可靠信息和不可靠信息,并试验验证SIGINT是可靠还是不可靠信息。
在Linux中,可靠信息是指在传输过程中不会丢失、重复或损坏的数据,而不可靠信息则可能会遇到这些问题。通常,TCP协议下的数据传输被认为是可靠信息,而UDP协议下的数据传输则被认为是不可靠信息。
SIGINT是一个信号,用于请求进程停止运行。在Linux中,SIGINT被认为是可靠信息,因为它可以保证被接收并执行相应的操作。例如,在终端中按下Ctrl+C会发送SIGINT信号给正在运行的程序,程序会接收到信号并停止运行。
2. 编程题
2.1. 编写程序实现如下功能:
- 程序A(A.c)按照用户输入的时间参数定时向程序B(B.c)发送信号,B.c程序接收到该信号后,打印输出一条信息并结束,运行示例如下:
- 先后台运行程序B;再运行A,A有两个参数,第一个是B的进程号(可以从命令ps -uax|grep B获取),第二个是定时时间(秒)。
运行示例:
$ ./B &
[9] 8329
$ ./A 8329 3
A: After 3 seconds, send a SIGALRM signal myself.
A: Sending a signal to process 8329...
B: Receiving a SIGINT signal.
编写C语言程序A.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
int target_pid;
int seconds;
void send_signal()
{
printf("A: Sending a signal to process %d...\n", target_pid);
kill(target_pid, SIGINT); // 发送信号
}
void sig_handler(int signo)
{
if (signo == SIGALRM)
printf("A: After %d seconds, send a SIGALRM signal myself.\n", seconds);
else if (signo == SIGINT)
{
printf("A: Received a SIGINT signal from B, exiting...\n");
exit(0);
}
}
int main(int argc, char *argv[])
{
if (argc != 3) {
printf("Usage: %s <pid> <seconds>\n", argv[0]);
exit(1);
}
target_pid = atoi(argv[1]);
seconds = atoi(argv[2]);
if (signal(SIGALRM, sig_handler) == SIG_ERR)
perror("signal");
if (signal(SIGINT, sig_handler) == SIG_ERR)
perror("signal");
alarm(seconds); // 设置定时器
printf("A: Program started, will send a signal after %d seconds.\n", seconds);
sleep(seconds); // 等待定时器到期
send_signal(); // 发送信号
while (1)
; // 等待SIGINT信号
}
编写C语言程序B.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sig_handler(int signo)
{
printf("B: Receiving a SIGINT signal.\n");
exit(0);
}
int main()
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
perror("signal");
printf("B: Program started, waiting for a signal...\n");
while (1)
; // 等待信号
}
运用gcc编译器进行程序编译
gcc -o A A.c
gcc -o B B.c
运行程序
./B &
[1] 3025
./A 3025 3
A: After 3 seconds, send a SIGALRM signal myself.
A: Sending a signal to process 3025...
B: Receiving a SIGINT signal.
2.2. 编写一个程序,实现以下功能:由父进程创建两个子进程,通过在终端输入“Ctrl+\”组合键向父进程发送SIGQUIT信号;父进程接收到这个信号后,向其两个子进程分别发送整数值为35的信号,子进程获得对应的信号后,终止运行;父进程调用wait函数等待两个子进程都终止后,再自我终止。
编写C语言程序signal_handling.c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void child_signal_handler(int signo)
{
printf("Child process %d received signal %d, terminating...\n", getpid(), signo);
exit(0);
}
void parent_signal_handler(int signo)
{
printf("Parent process %d received SIGQUIT signal, sending signals to child processes...\n", getpid());
// 向两个子进程发送信号
kill(0, SIGUSR1);
// 等待子进程终止
wait(NULL);
wait(NULL);
printf("All child processes terminated, parent process %d exiting...\n", getpid());
exit(0);
}
int main()
{
pid_t child1, child2;
// 创建第一个子进程
child1 = fork();
if (child1 == 0)
{
// 子进程1
signal(SIGUSR1, child_signal_handler);
while (1)
; // 持续等待信号
exit(0);
}
// 创建第二个子进程
child2 = fork();
if (child2 == 0)
{
// 子进程2
signal(SIGUSR1, child_signal_handler);
while (1)
; // 持续等待信号
exit(0);
}
// 父进程
signal(SIGQUIT, parent_signal_handler);
printf("Parent process %d created child processes %d and %d\n", getpid(), child1, child2);
printf("Press Ctrl+\\ to send SIGQUIT signal to parent process %d\n", getpid());
while (1)
; // 持续等待信号
return 0;
}
运用gcc编译器进行程序编译
gcc -o signal_handling signal_handling.c
运行程序
./signal_handling
2.3. 编写一个程序,实现以下功能:
- 搜索2~65535之间所有的素数并将其保存到数组中;
- 用户输入ctrl+c发出信号,程序打印出最近找到的素数,并继续搜索;
- 用户输入ctrl+\发出信号,程序退出运行,并打印出所有已找到的素数;
- 如没有发出信号,程序打印所有找到素数
编写C语言程序prime_search.c
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
int i = 1, a[30000], j = 0;
void sigHandler(int signalNum)
{
printf("最近找到的素数: %d\n", a[j - 1]);
}
int isPrime(int n)
{ // 判断n是否为素数
if (n == 1)
return 0;
if (n == 2)
return 1;
if (n % 2 == 0)
return 0; // 排除所有偶数
for (int i = 3; i * i <= n; i += 2) // 只需要判断奇数
if (n % i == 0)
return 0;
return 1;
}
int main()
{
signal(SIGINT, sigHandler);
while (i <= 65535)
{
if (isPrime(i))
a[j++] = i;
i++;
sleep(2);
}
return 0;
}
运用gcc编译器进行程序编译
gcc -std=c99 -o prime_search prime_search.c
运行程序
./prime_search
1. 用户输入ctrl+c发出信号,程序打印出最近找到的素数,并继续搜索;
2. 用户输入ctrl+\发出信号,程序退出运行,并打印出所有已找到的素数;
3. 如没有发出信号,程序打印所有找到素数
2.4. 利用alarm函数(也可以利用setitimer函数)编写文字时钟程序,实现数字时钟功能。printf输出利用\033格式化输出彩色文字时钟,格式自拟。
编写C语言程序``alarm_time.c`
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
void print_clock() {
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
// 格式化输出彩色文字时钟
printf("\033[2J"); // 清屏
printf("\033[1;1H"); // 移动光标到屏幕左上角
printf("\033[1;33m"); // 设置颜色为黄色
printf("%02d:%02d:%02d\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
printf("\033[0m"); // 恢复默认颜色
}
void sigHandler(int signalNum) {
print_clock();
alarm(1);
}
int main() {
signal(SIGALRM, sigHandler);
alarm(1);
while (1) {
pause();
}
return 0;
}
运用gcc编译器进行程序编译
gcc -o alarm_time alarm_time.c
运行程序
./alarm_time