在上次课的学习中,我们主要学习了四个基本的函数操作以及进程的相关问题。
一.函数
1.stat函数用于获取文件的属性
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
2.access函数用于测试文件是否拥有某种权限
#include <unistd.h>
int access(const char *pathname, int mode);
3.chmod函数用于修改文件的访问权限
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
4.truncate函数用于修改文件大小,常用于扩展文件,其功能与lseek函数类似
#include <sys/stat.h>
int truncate(const char *path, off_t length);
二.进程创建
1.进程的创建
#include <unistd.h>
pid_t fork(void);
2.fork()函数
test_fork.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
pid_t tempPid;
tempPid = fork();
if(tempPid == -1){
perror("fork error");
}else if(tempPid > 0){//parent
printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
}else{//child
printf("child process, pid = %d, ppid = %d\n", getpid(), getppid());
}//of if
printf("......finish......");
return 0;
}//of main
在该实例中,parent process可以显示出我们想要的结果,但是child process却没有得到我们的预期值,其ppid显示为1,原因是parent process 在完成输出后会被回收掉,所以child process的parent无了,会返回为init的pid值。
3.创建多个进程
int i;
for(i = 0; i < 2; i ++){
tempPid = fork();
}//of for i
按程序运行的话循环五次,会得到2的五次方个结果,但是我们希望可以得到五次结果,这就会造成干扰,输出了过多的无用信息,因此我们要在每次子进程完成输出之后对其进行回收来确保节约内存,我们进行如下的操作
test_fork2.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
pid_t tempPid;
int i;
for(i = 0; i < 2; i ++){
if((tempPid = fork()) == 0){
break;
}//of if
}//of for i
if(tempPid == -1){
perror("fork error");
}else if(tempPid > 0){//parent
printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
}else{//child
printf("I am child process = %d, pid = %d, ppid = %d\n", i + 1, getpid(), getppid());
}//of if
printf("......finish......");
return 0;
}//of main
这样就可以达到我们预期的结果,但需要注意的是子进程的输出并没有一定的顺序性,因为进程的优先级是相同的。终端提示符后面仍然有子进程信息打印,而命令提示符在最后一行的开头闪烁,这是因为Shell进程也是一个进程,和打印输出的优先级相同,都在竞争CPU的使用权。
3.进程的执行顺序:利用sleep函数,暂缓进程执行
test_fork3.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
pid_t tempPid;
int i;
for(i = 0; i < 2; i ++){
if((tempPid = fork()) == 0){
break;
}//of if
}//of for i
if(tempPid == -1){
perror("fork error");
}else if(tempPid > 0){//parent
sleep(2);
printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
}else{//child
sleep(i);
printf("I am child process = %d, pid = %d, ppid = %d\n", i + 1, getpid(), getppid());
}//of if
printf("......finish......");
return 0;
}//of main
在进行sleep操作时parent process的sleep时长多于child process,这样才能确保child的ppid能够输出正确的结果。
总的来说,上节课的主要核心还是对fork()函数的掌握,以及由此理解进程的相关问题,涉及此类问题都会出现两个进程,与我们以往的学习存在一定的差异。