Programming With POSIX Threads 讀書筆記(一)

我們現在編寫一個簡單的鬧鈴程序,允許用戶輸入一個時間,在這個時間過後鬧鐘顯示到達時間的文本消息。

#include "errors.h"
#include <stdio.h>

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

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

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

這是最簡單的不使用多線程的版本,在這個版本中。接收到用戶的輸入之後,主線程直接休眠相應的時間,在此期間程序無法接收其他任何的事件。


二:多線程版本

#include <sys/types.h>
#include <wait.h>
#include "errors.h"

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

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

		if (sscanf(line, "%d %64[^\n]", &seconds, message) < 2) {
			fprintf(stderr, "Bad Command\n");
		} else {
			pid = fork();
			if (pid == (pid_t) -1) //fork()函數失敗
				errno_abort("Fork");
			if (pid == (pid_t) 0) { //In The Child
				sleep(seconds);
				printf("(%d) %s\n", seconds, message);
				exit(0);
			} else { //In The Parent
				do {
					pid = waitpid((pid_t) -1, NULL, WNOHANG);
					if (pid == (pid_t) -1)
						errno_abort("Wait for child");
				} while (pid != (pid_t) 0);
			}
		}
	}
	return 0;
}

在這個版本里,main函數沒有直接調用sleep,而是創建了一個子進程,在子進程中異步地調用sleep函數,父進程則繼續接受用戶的輸入。fork函數的調用,會產生一個子進程,而這個子進程和父進程之間的區別就是這個函數的返回值。在子進程中,fork函數的返回值是0;而在父進程中,fork函數的返回值是子進程的pid;


三:多進程版本

#include <pthread.h>
#include "errors.h"

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

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

	status = pthread_detach(pthread_self());
	if (status != 0)
		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 (fgets(line, sizeof(line), stdin) == NULL) exit(0);
		if (strlen(line) <= 1 ) continue;
		alarm = (alarm_t*)malloc(sizeof(alarm_t));
		if (alarm == NULL)
			errno_abort("Allocate alarm");

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

多線程的版本和多進程版本的設計想法是一樣的,接收到一個用戶的輸入之後。馬上創建一個新的線程,讓線程異步地休眠,返回提示信息。主線程依舊處理用戶的輸入,創建線程。


但是我們可能要爲每一個鬧鐘實例創建一個線程。之後我們可能會給出新的版本專門負責等待鬧鐘的終止。


errors.h 文件

#ifndef ERRORS_H_
#define ERRORS_H_

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

#ifdef DEBUG
# define DPRINTF(arg) printf arg
#else
# define DPRINTF(arg)
#endif

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

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

#endif /* ERRORS_H_ */


Programming With POSIX Threads 讀書筆記(一)http://blog.csdn.net/hyzhou33550336/article/details/16890691

Programming With POSIX Threads 讀書筆記(二)http://blog.csdn.net/hyzhou33550336/article/details/16890959

Programming With POSIX Threads 讀書筆記(三)http://blog.csdn.net/hyzhou33550336/article/details/16899433

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章