同步和异步例子(linux)

《POSIX多线程程序设计》——David R.Buten

同步

alarm.c

#include 
#include 
#include 
#include 

int main(int argc, char *argv[]) {
    int seconds;
    char line[128];
    char message[64];

    while (1) {
        printf("Alarm> ");
        if (NULL == fgets(line, sizeof(line), stdin)) exit(0);
        if (1 >= strlen(line)) continue;

        if (2 > sscanf(line, "%d %64[^\n]", &seconds, message))
            fprintf(stderr, "Bad command\n");
        else {
            sleep(seconds);
            printf("(%d) %s\n", seconds, message);
        }
    }

    return 0;
}

gcc -o alarm alarm.c
同步和异步例子(linux)_第1张图片

局限性:一次只能处理一个闹钟请求。

异步(多进程)

alarm_fork.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define errno_abort(text) do { \
    fprintf(stderr, "%s at \"%s\":%d: %s\n", \
        text, __FILE__, __LINE__, strerror(errno)); \
    abort(); \
    } while (0)

int main(int argc, char *argv[]) {
    int status;
    char line[128];
    int seconds;
    pid_t pid;
    char message[64];

    while (1) {
        printf("Alarm> ");
        if (NULL == fgets(line, sizeof(line), stdin)) exit(0);
        if (1 >= strlen(line)) continue;

        if (2 > sscanf(line, "%d %64[^\n]", &seconds, message))
            fprintf(stderr, "Bad command\n");
        else {
            pid = fork();
            if ((pid_t)-1 == pid) // failure
                errno_abort("Fork"); 
            if ((pid_t)0 == pid) { // child 
                sleep(seconds);
                printf("(%d) %s\n", seconds, message);
                exit(0);
            }
            else { // parent
                do {        
                    pid = waitpid((pid_t)-1, NULL, WNOHANG); // 非阻塞等待子进程结束,回收子进程
                    //printf("#%d\n", pid);                 
                    if ((pid_t)-1 == pid)
                        errno_abort("Wait for child");
                } while ((pid_t)0 != pid);
            }
        }
    }   

    return 0;
}

gcc -o alarm_fork alarm_fork.c
同步和异步例子(linux)_第2张图片
alarm_fork.c中的main函数没有直接调用sleep函数 ,而是创建了一个子进程,在子进程中异步地调用sleep函数和printf,而父进程则继续运行。

调用waitpid函数回收子进程,并设置WNOHANG(父进程不必挂起等待子进程的结束)。

异步(多线程)

alarm_thread.c

#include 
#include 
#include 
#include 
#include 
#include 

#define err_abort(code, text) do { \
    fprintf(stderr, "%s at \"%s\":%d: %s\n", \
        text, __FILE__, __LINE__, strerror(errno)); \
    abort(); \
    } while (0)

#define errno_abort(text) do { \
    fprintf(stderr, "%s at \"%s\":%d: %s\n", \
        text, __FILE__, __LINE__, strerror(errno)); \
    abort(); \
    } while (0)

typedef struct alarm_tag {
    int seconds;
    char message[64];
} alarm_t;

void* alarm_thread(void *arg) {
    alarm_t *alarm = (alarm_t *)arg;
    int status;

    status = pthread_detach(pthread_self()); // 分离自己,在它终止后立刻回收
    if (0 != status) 
        err_abort(status, "Detach thread");
    sleep(alarm->seconds);
    printf("(%d) %s\n", alarm->seconds, alarm->message);
    free(alarm);
    return NULL;
}

int main(int argc, char *argv[]) {
    int status;
    char line[128];
    alarm_t *alarm;
    pthread_t thread;

    while (1) {
        printf("Alarm> ");
        if (NULL == fgets(line, sizeof(line), stdin)) exit(0);
        if (1 >= strlen(line)) continue;
        alarm = (alarm_t *)malloc(sizeof(alarm_t));
        if (NULL == alarm)
            errno_abort("Allocate alarm");

        if (2 > sscanf(line, "%d %64[^\n]", &alarm->seconds, alarm->message)) {
            fprintf(stderr, "Bad command\n");
            free(alarm);
        }   
        else {
            status = pthread_create(&thread, NULL, alarm_thread, alarm);
            if (0 != status)
                err_abort(status, "Create alarm thread");
        }
    }

    return 0;
}

gcc -o alarm_thread alarm_thread.c -lpthread
同步和异步例子(linux)_第3张图片

你可能感兴趣的:(▷,Linux)