1. 程式人生 > >同步和非同步例子(linux)

同步和非同步例子(linux)

《POSIX多執行緒程式設計》——David R.Buten

同步

alarm.c

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

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
這裡寫圖片描述

侷限性:一次只能處理一個鬧鐘請求。

非同步(多程序)

alarm_fork.c

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>

#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
2
alarm_fork.c中的main函式沒有直接呼叫sleep函式 ,而是建立了一個子程序,在子程序中非同步地呼叫sleep函式和printf,而父程序則繼續執行。

呼叫waitpid函式回收子程序,並設定WNOHANG(父程序不必掛起等待子程序的結束)。

非同步(多執行緒)

alarm_thread.c

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#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
3