学习计时:共xxx小时 读书: 代码: 作业: 博客: |
一、学习目标 |
掌握进程控制 掌握信号处理的方法 掌握管道和fifo进行进程间通信的方法 |
二、学习资源 |
编译、运行、阅读、理解process.tar.gz压缩包中的代码 |
三、学习方法 |
1. 进度很重要:必须跟上每周的进度,阅读,练习,问答,项目。我会认真对待每一位同学,请你不要因为困难半途而废。
2. 问答很重要:遇到知识难点请多多提问,这是你的权利更是您对自己负责的义务。问答到博客园讨论小组:http://group.cnblogs.com/103791/
3. 实践很重要:解决书中习题,实践书中实例,完成每周项目,才算真的消化了这本好书。通过实验楼环境或自己安装的虚拟机在实践中进行学习
4. 实验报告很重要:详细记录你完成项目任务的思路,获得老师点评和帮助自己复习。学习完成后在博客园中(http://www.cnblogs.com/)把学习过程通过博客发表,博客标题“信息安全系统设计基础第三周学习总结”
|
四、学习任务 |
(提示:请将要求学生完成的任务、测验或思考题列在此处)
|
五、后续学习预告(可选): |
第十二章《并发编程》 |
六、学习过程 |
一. execvp()函数:execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。 exec1.c
#include <stdio.h> #include <unistd.h> int main() { char *arglist[3]; arglist[0] = "ls"; arglist[1] = "-l"; arglist[2] = 0 ;//NULL printf("* * * About to exec ls -l\n"); execvp( "ls" , arglist ); printf("* * * ls is done. bye"); return 0; } exec1.c、exec2.c、exec3.c运行结果一样。
二. fork()函数:在Unix/Linux中用fork函数创建一个新的进程。进程是由当前已有进程调用fork函数创建,分叉的进程叫子进程,创建者叫父进程。该函数的特点是调用一次,返回两次,一次是在父进程,一次是在子进程。两次返回的区别是子进程的返回值为0,父进程的返回值是新子进程的ID。子进程与父进程继续并发运行。如果父进程继续创建更多的子进程,子进程之间是兄弟关系,同样子进程也可以创建自己的子进程,这样可以建立起定义关系的进程之间的一种层次关系。
调用fork函数之后内核的工作过程: 1.分配新的内存块和内核数据结构 2.复制原来的进程到新的进程 3.向运行进程集添加新的进程 4.将控制返回给两个进程
forkdemo.c #include <stdio.h> #include<stdlib.h> #include<unistd.h>
int main() { int fork_rv;
printf("Before: my pid is %d\n", getpid());
fork_rv = fork(); /* create new process */
if ( fork_rv == -1 ) /* check for error */ perror("fork");
else if ( fork_rv == 0 ){ printf("I am the child. my pid=%d\n", getpid()); printf("parent pid= %d, my pid=%d\n", getppid(), getpid()); exit(0); }
else{ printf("I am the parent. my child is %d\n", fork_rv); sleep(10); exit(0); }
return 0; } fork有五个程序,其中forkdemo2.c的子进程不是从main函数开始,而是从fork返回的地方开始被创建。
三.psh1.c:psh1.c是Unix shell的第一个方案,要求每个字符串单独输入,第一个是程序名,然后依次是程序参数。
代码中 1.一个字符串,一个字符串构造参数列表argist,最后在数组末尾加上NULL; 2.将arglist[0]和arglist数组传给execvp。 3.程序正常运行,execvp命令指定的程序代码覆盖了shell程序代码,并在命令结束之后退出,shell就不能再接受新的命令。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include<unistd.h>
#define MAXARGS 20 #define ARGLEN 100
int execute( char *arglist[] ) { execvp(arglist[0], arglist); perror("execvp failed"); exit(1); }
char * makestring( char *buf ) { char *cp;
buf[strlen(buf)-1] = '\0'; cp = malloc( strlen(buf)+1 ); if ( cp == NULL ){ fprintf(stderr,"no memory\n"); exit(1); } strcpy(cp, buf); return cp; }
int main() { char *arglist[MAXARGS+1]; int numargs; char argbuf[ARGLEN];
numargs = 0; while ( numargs < MAXARGS ) { printf("Arg[%d]? ", numargs); if ( fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n' ) arglist[numargs++] = makestring(argbuf); else { if ( numargs 0 ){ arglist[numargs]=NULL; execute( arglist ); numargs = 0; } } } return 0; }
四.wait
1.waitdemo1.c:进程通过调用wait函数等待子进程的退出。wait首先暂停调用它的进程直到子进程结束,然后wait取得子进程结束时传给exit的值。显示了子进程调用exit触发wait返回父进程的过程。
2.waitdemo2.c:显示了wait函数告诉父进程子进程是如何结束的,通过传递给wait的参数。父进程调用wait时传一个整型变量地址给函数,内核将子进程的退出状态保存在这个变量之中。 wait的两个重要特征: 1.wait阻塞调用它的程序直到子进程结束 2.wait返回结束进程的PID
#include <stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/wait.h> #include<unistd.h>
#define DELAY 10
void child_code(int delay) { printf("child %d here. will sleep for %d seconds\n", getpid(), delay); sleep(delay); printf("child done. about to exit\n"); exit(27); }
void parent_code(int childpid) { int wait_rv; int child_status; int high_8, low_7, bit_7;
wait_rv = wait(&child_status); printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv);
high_8 = child_status >> 8; /* 1111 1111 0000 0000 */ low_7 = child_status & 0x7F; /* 0000 0000 0111 1111 */ bit_7 = child_status & 0x80; /* 0000 0000 1000 0000 */ printf("status: exit=%d, sig=%d, core=%d\n", high_8, low_7, bit_7); }
int main() { int newpid;
printf("before: mypid is %d\n", getpid());
if ( (newpid = fork()) == -1 ) perror("fork"); else if ( newpid == 0 ) child_code(DELAY); else parent_code(newpid); }
五.视频总结: 视频中主要讲了管道。 1. Linux下的各种进程间通信方式包括:管道、命名管道、消息队列、共享内存、信号量。
|
七、遇到的问题及解决 |
(提示:此处由学生填写,是重要的得分点,要写出遇到的问题和解决方案以及对出现问题的思考)
|
八、其他 |
linux好难啊!!!! |