TLPI 21.1.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
#define _XOPEN_SOURCE 600
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <crypt.h> 
#include "tlpi_hdr.h"

static char *str2;
static int handled = 0;

// 设置处理器函数,一旦遇上SIGINT,便对str2进行加密
static void handler(int sig) {
    crypt(str2, "xx");
    handled++;
}

int main(int argc, char *argv[]) {
    char *cr1;
    int callNum, mismatch;
    struct sigaction sa;

    if (argc != 3) 
        usageErr("%s str1 str2\n", argv[0]);

    str2 = argv[2];

    // 对str1进行加密,并将结果保存到独立缓冲区中
    cr1 = strdup(crypt(argv[1], "xx"));

    if (cr1 == NULL)
        errExit("strdup");
    sigemptyset(&sa.sa_mask);   // 初始化在执行处理器函数时将阻塞的信号
    sa.sa_flags = 0;    // 即sa.sa_flags = SIG_BLOCK
    sa.sa_handler = handler;    // 设置信号处理器函数的地址

    if (sigaction(SIGINT, &sa, NULL) == -1)
        errExit("sigaction");


    for (callNum = 1, mismatch = 0; ; callNum++) {
        if (strcmp(crypt(argv[1], "xx"), cr1) != 0) {
            mismatch++;
            printf("Mismatch on call %d (mismatch=%d handled=%d)\n", callNum, mismatch, handled);
        }
    }
}

解释

crypt()

需要加入#include <crypt.h>,如果不加上该头文件,会出现implicit declaration of function ‘crypt’的错误。

针对于undefined reference to `crypt’的错误,stackoverflow有以下方案:

crypt.c:(.text+0xf1): undefined reference to ‘crypt’ is a linker error. Try linking with -lcrypt : gcc crypt.c -lcrypt.

即,在CMakeLists.txt文件中加入link_libraries(crypt)

for循环内部

在这个无限循环中,不断对str1进行加密,并与正确结果进行比较。如果str1在加密的过程中不被打断,则会得到正确结果,但是如果被打断并在处理器函数中对str2进行加密,则会对str1加密的结果产生污染,导致该加密的结果不正确,以此来判断信号处理器函数是否对不可重入函数产生了影响。