实验8

1.1

  • 可靠信号(Reliable Signals): 这种信号在发送时不会丢失,系统会确保信号最终被接收。当进程处于阻塞状态时,可靠信号会被排队,直到进程解除阻塞后才被传递。SIGINT通常被认为是可靠信号。

  • 不可靠信号(Unreliable Signals): 这种信号可能在发送时丢失,而且不会在信号过多导致排队不足时保存。进程在信号未被处理完全之前,可能不会接收到新的信号。SIGIO和SIGURG通常被认为是不可靠信号。

    不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号丢失,而后者不会。非可靠信号一般都有确定的用途及含义,可靠信号则可以让用户自定义使用。

试验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// SIGINT信号处理函数
void signal_handler(int sig) {
printf("\nReceived SIGINT. Processing and saving critical information...\n");

// 模拟处理过程
sleep(2);

printf("Critical information processed and saved.\n");
}

int main() {
// 注册SIGINT信号处理函数
signal(SIGINT, signal_handler);

// 模拟程序的主要逻辑
while (1) {
// 在这里添加程序的主要逻辑
printf("Working...\n");
sleep(1);
}

return 0;
}

结果:

2.1

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//A.c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

int target_process_id;

void alarm_handler(int signum) {
if (signum == SIGALRM) {
printf("A: Sending a SIGALRM signal to process %d...\n", target_process_id);
kill(target_process_id, SIGALRM); // 发送 SIGALRM 信号给程序 B
}
}

int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <B_process_id> <timer_seconds>\n", argv[0]);
return 1;
}

target_process_id = atoi(argv[1]);
int timer_seconds = atoi(argv[2]);

// 设置 SIGALRM 信号处理函数
signal(SIGALRM, alarm_handler);

printf("A: After %d seconds, send a SIGALRM signal myself.\n", timer_seconds);

// 设置定时器
alarm(timer_seconds);

// 等待定时器触发
pause();

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//B.c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void sigalrm_handler(int signum) {
if (signum == SIGALRM) {
printf("B: Receiving a SIGALRM signal. Exiting...\n");
// 执行程序 B 的其他操作...
exit(0);
}
}

int main() {
// 设置 SIGALRM 信号处理函数
signal(SIGALRM, sigalrm_handler);

// 输出进程 ID
printf("B: My process ID is %d\n", getpid());

// 保持程序 B 持续运行
while (1) {
sleep(1);
}

return 0;
}

结果:

‘&’表后台运行

2.2

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

void sigquit_handler(int signum) {
if (signum == SIGQUIT) {
printf("Parent: Received SIGQUIT signal. Sending signals to children...\n");

// 向两个子进程发送信号
kill(0, SIGUSR1); // 向同一进程组的所有进程发送 SIGUSR1 信号
}
}

void sigusr1_handler(int signum) {
if (signum == SIGUSR1) {
printf("Child: Received SIGUSR1 signal. Exiting...\n");
exit(0);
}
}

int main() {
// 设置 SIGQUIT 信号处理函数
signal(SIGQUIT, sigquit_handler);

// 创建第一个子进程
pid_t child_pid1 = fork();

if (child_pid1 == -1) {
perror("Error creating child process 1");
exit(EXIT_FAILURE);
}

if (child_pid1 == 0) { // 子进程1
signal(SIGUSR1, sigusr1_handler);

while (1) {
// 子进程1执行的任务
sleep(1);
}
}

// 创建第二个子进程
pid_t child_pid2 = fork();

if (child_pid2 == -1) {
perror("Error creating child process 2");
exit(EXIT_FAILURE);
}

if (child_pid2 == 0) { // 子进程2
signal(SIGUSR1, sigusr1_handler);

while (1) {
// 子进程2执行的任务
sleep(1);
}
}

// 等待子进程退出
int status1, status2;
waitpid(child_pid1, &status1, 0);
waitpid(child_pid2, &status2, 0);

// 当收到 SIGQUIT 信号时,会执行到这里
printf("Parent: Both children have exited. Exiting...\n");

return 0;
}

结果:

2.3

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdbool.h>

#define MAX_PRIMES 1000

int primes[MAX_PRIMES];
int num_primes = 0;

bool is_prime(int number) {
if (number < 2) {
return false;
}

for (int i = 2; i * i <= number; ++i) {
if (number % i == 0) {
return false;
}
}

return true;
}

void handle_sigint(int signum) {
if (signum == SIGINT) {
printf("\nLast prime found: %d\n", primes[num_primes - 1]);
fflush(stdout);
}
}

void handle_sigquit(int signum) {
if (signum == SIGQUIT) {
printf("\nAll primes found:\n");
for (int i = 0; i < num_primes; ++i) {
printf("%d ", primes[i]);
}
printf("\nExiting...\n");
exit(EXIT_SUCCESS);
}
}

int main() {
// 设置信号处理函数
signal(SIGINT, handle_sigint);
signal(SIGQUIT, handle_sigquit);

printf("Searching for primes between 2 and 65535...\n");

for (int i = 2; i <= 65535; ++i) {
if (is_prime(i)) {
primes[num_primes++] = i;

// 打印找到的素数
//printf("%d ", i);
fflush(stdout);

// 添加睡眠函数,使效果明显
sleep(1);
}
}

return 0;
}

结果:

2.4

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>

void displayDateTime() {
time_t currentTime;
struct tm *localTime;

currentTime = time(NULL);
localTime = localtime(&currentTime);

// 使用 \033 进行颜色设置,\033[0m 恢复默认颜色
printf("\033[34;47m%04d-%02d-%02d %02d:%02d:%02d\033[0m\n",
localTime->tm_year + 1900, localTime->tm_mon + 1, localTime->tm_mday,
localTime->tm_hour, localTime->tm_min, localTime->tm_sec);
}

void handleAlarm(int signum) {
// 重置闹钟
alarm(1);
displayDateTime();
}

int main() {
// 注册信号处理函数
signal(SIGALRM, handleAlarm);

// 初次触发闹钟
alarm(1);

// 主循环
while (1) {
// 空循环等待信号
}

return 0;
}

结果:

参考例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//digital_clock.c

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

void alarm_handler(int signo)
{
if(signo == SIGALRM)
{
char date_str[100];
char time_str[100];
time_t t=time(NULL);
struct tm *tp=localtime(&t);
strftime(date_str, sizeof(date_str),"%Y-%m-%d", tp);
strftime(time_str, sizeof(time_str),"%H:%M:%S", tp);
printf("\033c"); //清屏命令
printf(" \033[35;47m%s\033[0m ", date_str);
printf("\033[31;43m%s\033[0m\n", time_str);
}
}

void show_time()
{
if( signal(SIGALRM, alarm_handler) == SIG_ERR )
{
perror("signal SIGALAM error");
exit(1);
}
alarm(1);
pause(); //等待定时器触发完成
}

int main()
{
while(1) {
show_time();
}

return 0;
}
  1. time_t t = time(NULL);

这行代码使用 time 函数获取当前时间,并将其表示为一个从 1970 年 1 月 1 日(UNIX 时代开始)到现在的秒数,这个值被存储在 time_t 类型的变量 t 中。time(NULL) 是一种常见的写法,表示获取当前时间。

  1. struct tm *tp = localtime(&t);

这行代码使用 localtime 函数将上述获取的当前时间(以秒数为单位)转换为一个 struct tm 结构体,这个结构体描述了日期和时间的各个部分(例如年、月、日、时、分和秒)。localtime 函数返回一个指向这个结构体的指针,该指针被存储在 struct tm 类型的指针变量 tp 中。

通过这两行代码,你得到了一个 structtm 类型的结构体指针 tp,它可以让你访问和操作当前的日期和时间。例如,你可以使用 tp->tm_year 来获取当前的年份,使用 tp->tm_mday 来获取当前的月份等等。

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2022-2024 CoffeeLin
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信