进程对 | 并发么? |
---|---|
AB | × |
AC | √ |
AD | √ |
BC | √ |
BD | √ |
CD | √ |
A. fork
B. longjmp execve
C. setjmp
4次,画画进程图就行了
8次
x=4
x=3
x=2
3
5
counter = 2
hello 0 1 Bye 2 Bye
hello 1 0 Bye 2 Bye
hello 1 Bye 0 2 Bye
BD
2^n
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void unix_error(char *msg) /* Unix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
void Execve(const char *filename, char *const argv[], char *const envp[])
{
if (execve(filename, argv, envp) < 0)
unix_error("Execve error");
}
int main(int argc, char **argv, char **env) {
Execve("/bin/ls", argv, env);
return 0;
}
abc 或 bac
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXARGS 128
#define MAXLINE 8192 /* Max text line length */
extern char **environ; /* Defined by libc */
/* Linux C中environ 变量是一个char** 类型,存储着系统的环境变量 */
void unix_error(char *msg) /* Unix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
void app_error(char *msg) /* Application error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}
pid_t Wait(int *status)
{
pid_t pid;
if ((pid = wait(status)) < 0)
unix_error("Wait error");
return pid;
}
char *Fgets(char *ptr, int n, FILE *stream)
{
char *rptr;
if (((rptr = fgets(ptr, n, stream)) == NULL) && ferror(stream))
app_error("Fgets error");
return rptr;
}
/* parseline - Parse the command line and build the argv array */
int parseline(char *buf, char **argv)
{
char *delim; /* Points to first space delimiter */
int argc; /* Number of args */
int bg; /* Background job? */
buf[strlen(buf)-1] = ' '; /* Replace trailing '\n' with space */
while (*buf && (*buf == ' ')) /* Ignore leading spaces */
buf++;
/* Build the argv list */
argc = 0;
while ((delim = strchr(buf, ' '))) {
argv[argc++] = buf;
*delim = '\0';
buf = delim + 1;
while (*buf && (*buf == ' ')) /* Ignore spaces */
buf++;
}
argv[argc] = NULL;
if (argc == 0) /* Ignore blank line */
return 1;
/* Should the job run in the background? */
if ((bg = (*argv[argc-1] == '&')) != 0)
argv[--argc] = NULL;
return bg;
}
pid_t Fork(void)
{
pid_t pid;
if ((pid = fork()) < 0)
unix_error("Fork error");
return pid;
}
int mysystem(char *command) {
char *Argv[MAXARGS];
int status;
if(Fork() == 0) {
parseline(command, Argv);
for(int i = 0; i < MAXARGS; i++) {
if(Argv[i]==NULL) {
break;
}
}
execve("/bin/sh", Argv, environ);
}
Wait(&status); /*等待子进程结束*/
return WEXITSTATUS(status);
}
int main(int argc, char **argv, char **env) {
char str[12] = "/bin/sh -c ";
char command[MAXLINE];
char temp[MAXLINE-12];
printf("\033[1;32m>\033[0m ");
while(Fgets(temp, MAXLINE-12, stdin)) {
strcpy(command, str);
strcat(command, temp);
printf("\033[1;32m mysystem 返回值为 %d \n\033[0m", mysystem(command));
printf("\033[1;32m\n>\033[0m ");
}
return 0;
}
我并没有使用 “csapp.h” 头文件,而是用到什么就复制出什么,一方面可以清楚被封装函数的调用方法,另一方面可以学习作者是如何对函数进行封装的。
我做的有些麻烦,虽然使用了 parseline 函数,但是我的代码只支持不带参数的 command,比如 “/bin/sh ls -a”,就只能识别到 “/bin/sh ls”,可以修改 parseline 函数,不过我懒 (ಥ _ ಥ)
对于几种不同的输入,有不同的返回值:
USER@NAME:~# ./mysystem
> ls
123.py 公共 模板
.........
mysystem 返回值为 0
> ./exit12
mysystem 返回值为 12
> lllll
/bin/sh: 1: lllll: not found
mysystem 返回值为 127
exit12 程序非常简单,只有四行:
#include
#include
int main() {
exit(12);
}
一个进程的待处理信号不会排队,只会被丢弃。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 2
const char CONSTINT[10] = "HAHA"; //只读常量
void unix_error(char *msg) /* Unix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
pid_t Waitpid(pid_t pid, int *iptr, int options)
{
pid_t retpid;
if ((retpid = waitpid(pid, iptr, options)) < 0)
unix_error("Waitpid error");
return(retpid);
}
pid_t Fork(void)
{
pid_t pid;
if ((pid = fork()) < 0)
unix_error("Fork error");
return pid;
}
int main()
{
int status, i;
pid_t pid;
for (i = 0; i < N; i++)
if ((pid = Fork()) == 0) { /* Child */
scanf("%s", &CONSTINT); //访问只读常量
exit(100 + i);
}
while ((pid = waitpid(-1, &status, 0)) > 0) {
if (WIFEXITED(status)) {
printf("child %d terminated normally with exit status=%d\n",
pid, WEXITSTATUS(status));
}
else if(WIFSIGNALED(status)) {
//const char *s;
printf("child %d terminated by signal %d:", pid, WTERMSIG(status));
fflush(stdout);
psignal(WTERMSIG(status), NULL);
}
}
if (errno != ECHILD)
unix_error("waitpid error");
exit(0);
}
USER@NAME:~# gcc -o P8-24 P8-24.c
USER@NAME:~# ./P8-24
123123
child 11345 terminated by signal 11: Segmentation fault
22
child 11344 terminated by signal 11: Segmentation fault
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
sigjmp_buf buf;
unsigned int Alarm(unsigned int seconds) {
return alarm(seconds);
}
void handler(int sig)
{
siglongjmp(buf, 1);
}
char *tfgets(char *s, int size, FILE *stream) {
signal(SIGALRM, handler);
if (!sigsetjmp(buf, 1)) {
Alarm(5);
fgets(s, size, stream);
}
else {
return NULL;
}
signal(SIGALRM, SIG_DFL);
return s;
}
int main()
{
while(1) {
char s[50];
char *temp = tfgets(s, 50, stdin);
if(temp == NULL) {
printf("超时\n\n");
} else {
printf("输入的字符串是:%s\n", temp);
}
}
exit(0);
}