This repository has been archived by the owner on Jun 28, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 168
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
719 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Makefile for ex8-26 | ||
|
||
# [email protected] | ||
# 2013-7-7 | ||
|
||
CC = gcc | ||
CFLAGS = -Wall | ||
|
||
PROGRAM += t | ||
PROGRAM += t-job | ||
|
||
OBJS += ex8-26.o | ||
OBJS += random_fork.o | ||
OBJS += job.o | ||
|
||
TOBJS += t-job.o | ||
|
||
PHONY += all | ||
PHONY += clean | ||
PHONY += TAGS | ||
|
||
.PHONY: $(PHONY) | ||
|
||
all: $(PROGRAM) | ||
|
||
t: $(OBJS) | ||
$(CC) $(CFLAGS) $^ -o $@ | ||
|
||
t-job: t-job.o job.o | ||
$(CC) $(CFLAGS) $^ -o $@ | ||
|
||
ex8-26.o: shellex.c | ||
$(CC) $(CFLAGS) -c $< -o $@ | ||
|
||
t-job.o: t-job.c job.h | ||
job.o: job.c job.h | ||
|
||
TAGS: | ||
find . -type f -name "*.[ch]" -print | xargs etags - | ||
|
||
clean: | ||
rm -f $(PROGRAM) $(OBJS) $(TOBJS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
/* | ||
* 8.26 | ||
* | ||
* [email protected] | ||
* 2013-7-14 | ||
* | ||
* 这个文件包含了用来处理作业控制的代码 | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include "job.h" | ||
|
||
/* | ||
* 作业控制列表从 1 开始计数,第 0 个位置是前台进程组 | ||
*/ | ||
|
||
static const int beg = 1; | ||
static int max, end; | ||
static struct job **job; | ||
|
||
/* empty: 1, otherwise: 0 */ | ||
int is_empty(struct job *job_list[], int len) | ||
{ | ||
int i; | ||
for (i = beg; i < len; i++) { | ||
if (job_list[i]) | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
|
||
void init_job(void) | ||
{ | ||
/* Background */ | ||
max = 2; | ||
end = 1; | ||
job = malloc(sizeof(struct job *) * max); | ||
if (!job) { | ||
fprintf(stderr, "init_job: malloc error\n"); | ||
exit(-1); | ||
} | ||
|
||
/* Foreground */ | ||
job[0] = malloc(sizeof(struct job)); | ||
if (!job[0]) { | ||
fprintf(stderr, "init_job: init foreground process failed!\n"); | ||
free_job(); | ||
exit(-1); | ||
} | ||
job[0]->command = NULL; | ||
} | ||
|
||
void free_job(void) | ||
{ | ||
int i; | ||
for (i = 0; i < end; i++) | ||
free(job[i]); | ||
free(job); | ||
} | ||
|
||
int add_job(pid_t pgid, int state, char *command, int len) | ||
{ | ||
struct job *j = malloc(sizeof(struct job)); | ||
if (!j) | ||
goto malloc_failed; | ||
j->pgid = pgid; | ||
j->state = state; | ||
j->command = malloc(len); | ||
if (!j->command) | ||
goto malloc_failed; | ||
memmove(j->command, command, len); | ||
|
||
if (end != beg && is_empty(job, end)) | ||
end = beg; | ||
if (end+1 == max) { | ||
struct job **old_job = job; | ||
int new_max = max * 3 / 2; | ||
job = realloc(old_job, new_max*sizeof(struct job *)); | ||
if (!job) { | ||
job = old_job; | ||
free(j->command); | ||
goto malloc_failed; | ||
} | ||
max = new_max; | ||
} | ||
job[end] = j; | ||
end += 1; | ||
printf("add_job: job list %d long now\n", end); | ||
|
||
return 0; | ||
|
||
malloc_failed: | ||
perror("malloc"); | ||
fprintf(stderr, "add_job: malloc failed!\n"); | ||
free(j); /* 释放 NULL 是无害的 */ | ||
return -1; | ||
} | ||
|
||
int find_job(pid_t pgid) | ||
{ | ||
int i; | ||
for (i = beg; i < end; i++) | ||
if (job[i] && job[i]->pgid == pgid) | ||
return i; | ||
return -1; | ||
} | ||
|
||
void delete_job(pid_t pgid) | ||
{ | ||
int jid = find_job(pgid); | ||
if (jid >= beg) { | ||
free(job[jid]); | ||
job[jid] = NULL; | ||
} | ||
} | ||
|
||
void update_job(pid_t pgid, int state) | ||
{ | ||
int jid = find_job(pgid); | ||
if (beg <= jid && jid < end) { | ||
job[jid]->state = state; | ||
printf("[%d] %d %s\n", jid, (int)pgid, job[jid]->command); | ||
} else { | ||
printf("%d: No such process\n", (int)pgid); | ||
} | ||
} | ||
|
||
pid_t get_pgid(int jid) | ||
{ | ||
if (jid < end && job[jid]) | ||
return job[jid]->pgid; | ||
return -1; | ||
} | ||
|
||
void print_job(int i) | ||
{ | ||
printf("[%d] %d", i, (int)job[i]->pgid); | ||
char *job_state; | ||
if (job[i]->state == JOB_RUNNING) | ||
job_state = "Running"; | ||
else if (job[i]->state == JOB_STOPPED) | ||
job_state = "Stopped"; | ||
else if (job[i]->state == JOB_DONE) | ||
job_state = "Done"; | ||
else | ||
job_state = "Unkown"; | ||
printf(" %s %s\n", job_state, job[i]->command); | ||
} | ||
|
||
void print_job_by_pgid(pid_t pgid) | ||
{ | ||
int jid = find_job(pgid); | ||
print_job(jid); | ||
} | ||
|
||
void print_all_job(void) | ||
{ | ||
int i; | ||
for (i = beg; i < end; i++) { | ||
if (!job[i]) | ||
continue; | ||
print_job(i); | ||
if (job[i]->state == JOB_DONE) | ||
delete_job(job[i]->pgid); | ||
} | ||
} | ||
|
||
void print_foreground(void) | ||
{ | ||
if (job[0]->command) | ||
printf("%s\n", job[0]->command); | ||
} | ||
|
||
void set_foreground(pid_t pgid, char *command, int len) | ||
{ | ||
job[0]->pgid = pgid; | ||
job[0]->state = JOB_RUNNING; | ||
job[0]->command = malloc(len); | ||
if (!job[0]->command) { | ||
perror("malloc"); | ||
exit(-1); | ||
} | ||
memmove(job[0]->command, command, len); | ||
} | ||
|
||
pid_t foreground_pgid(void) | ||
{ | ||
return job[0]->pgid; | ||
} | ||
|
||
void get_foreground_command(char *command) | ||
{ | ||
int len = strlen(job[0]->command) + 1; | ||
memmove(command, job[0]->command, len); | ||
} | ||
|
||
void move_to_background(pid_t pgid, int state, char *command, int len) | ||
{ | ||
int jid = find_job(pgid); | ||
if (jid < 0) | ||
add_job(pgid, state, command, len); | ||
else | ||
update_job(pgid, state); | ||
} | ||
|
||
void move_to_foreground(pid_t pgid) | ||
{ | ||
int jid = find_job(pgid); | ||
if (jid >= beg) | ||
*job[0] = *job[jid]; | ||
else | ||
printf("%d: No such process\n", (int)pgid); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* 8.26 | ||
* | ||
* [email protected] | ||
* 2013-7-14 | ||
*/ | ||
|
||
#ifndef __job_h | ||
#define __job_h | ||
|
||
#include <unistd.h> | ||
|
||
#define JOB_RUNNING 0 | ||
#define JOB_STOPPED 1 | ||
#define JOB_DONE 2 | ||
|
||
struct job { | ||
pid_t pgid; /* 进程组 ID */ | ||
int state; /* 作业状态 */ | ||
char *command; /* 运行作业的命令 */ | ||
}; | ||
|
||
extern void init_job(void); | ||
extern int add_job(pid_t pgid, int state, char *command, int len); | ||
extern void delete_job(pid_t pgid); | ||
extern int find_job(pid_t pgid); | ||
extern void free_job(void); | ||
extern void update_job(pid_t pgid, int state); | ||
|
||
extern pid_t get_pgid(int jid); | ||
|
||
extern void print_job(int i); | ||
extern void print_job_by_pgid(pid_t pgid); | ||
extern void print_all_job(void); | ||
|
||
extern pid_t foreground_pgid(void); | ||
extern void get_foreground_command(char *command); | ||
extern void print_foreground(void); | ||
extern void set_foreground(pid_t pgid, char *command, int len); | ||
extern void move_to_background(pid_t pgid, int state, char *command, int len); | ||
extern void move_to_foreground(pid_t pgid); | ||
|
||
#endif /* __job_h */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* p521 -- code/ecf/rfork.c | ||
* | ||
* 下面的代码包含了一个暴露竞争的简便技巧 | ||
* | ||
* 像 procmask2.c 那样的竞争难以发现,因为它们依赖于内核相关的调度决策。在一次 | ||
* fork() 调用之后,有些内核调度子进程先运行,而有些内核调度父进程先运行。如果你 | ||
* 要在后一种系统上运行 procmask1.c 的代码,它绝不会失败,无论你测试多少遍。但是 | ||
* 一旦在前一种系统上运行这段代码,那么竞争就会暴露出来,代码会失败。 | ||
* | ||
* 下面的代码是一个 fork() 的包装函数,它随机地决定父进程和子进程执行的顺序。父进 | ||
* 程和子进程扔一枚硬币来决定谁会休眠,因而给另一个进程被调度的机会。 | ||
* | ||
* 如果我们运行这个代码多次,那么我们就有极高的概率会测试到父子进程执行的两种顺序, | ||
* 无论这个特定内核的调度策略是什么样子的。 | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <sys/time.h> | ||
#include <sys/types.h> | ||
|
||
/* Sleep for a random period between [0, MAX_SLEEP] us. */ | ||
#define MAX_SLEEP 100000 | ||
|
||
/* Macro that maps val into the range [0, RAND_MAX] */ | ||
#define CONVERT(val) (((double)val)/(double)RAND_MAX) | ||
|
||
pid_t random_fork(void) | ||
{ | ||
static struct timeval time; | ||
unsigned bool, secs; | ||
pid_t pid; | ||
|
||
/* Generate a different seed each time the function is called */ | ||
gettimeofday(&time, NULL); | ||
srand(time.tv_usec); | ||
|
||
/* Determine whether to sleep in parent of child and for how long */ | ||
bool = (unsigned)(CONVERT(rand()) + 0.5); | ||
secs = (unsigned)(CONVERT(rand()) * MAX_SLEEP); | ||
|
||
/* Call the real fork function */ | ||
if ((pid = fork()) < 0) | ||
return pid; | ||
|
||
/* Randomly decide to sleep in the parent or the child */ | ||
if (pid == 0) { /* Child */ | ||
if (bool) { | ||
usleep(secs); | ||
} | ||
} | ||
else { /* Parent */ | ||
if (!bool) { | ||
usleep(secs); | ||
} | ||
} | ||
|
||
/* Return the PID like a normal fork call */ | ||
return pid; | ||
} |
Oops, something went wrong.