《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;
}
局限性:一次只能处理一个闹钟请求。
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
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;
}