- 系统调用
- main.c 先open再fork
- main.c 先fork再open
- main.c 打印fd的值
- 第一种情况
- 第二种情况
- 用户空间、内核空间
- 系统调用和库函数的区别
- 替换进程
- test.c
- execl
- execlp
- execle
- execv
- execvp
- execve
PCB进程控制块进程描述符==struct task_struct
fork是写时拷贝技术,提高了效率
open read write close *** 作文件的系统调用 实现在内核中
fopen fread fgets fwrite fclse 库函数 /usr/lib/libc.so
file.txt
abcdefmain.c 先open再fork
#include#include #include #include #include #include int main() { int fd=open("file.txt",O_RDONLY);//父进程打开 assert(fd!=-1); pid_t pid=fork(); assert(pid!=-1); if(pid==0) { char buff[32]={0}; read(fd,buff,1); printf("child buff=%sn",buff); sleep(1); read(fd,buff,1); printf("child buff=%sn",buff); } else { char buff[32]={0}; read(fd,buff,1); printf("parent buff=%sn",buff); sleep(1); read(fd,buff,1); printf("parent buff=%sn",buff); } close(fd); exit(0); }
结果
stu@stu-virtual-machine:~/Linux/day09$ cat file.txt abcdef stu@stu-virtual-machine:~/Linux/day09$ ./main parent buff=a child buff=b child buff=c parent buff=d
文件偏移量
先open后fork
父进程打开的文件fork之后会被子进程复制过去(相当于子进程自己没有做open,而是继承了父进程的打开)
main.c 先fork再open#include#include #include #include #include #include int main() { pid_t pid=fork(); assert(pid!=-1); int fd=open("file.txt",O_RDONLY);//父进程打开 assert(fd!=-1); if(pid==0) { char buff[32]={0}; read(fd,buff,1); printf("child buff=%sn",buff); sleep(1); read(fd,buff,1); printf("child buff=%sn",buff); } else { char buff[32]={0}; read(fd,buff,1); printf("parent buff=%sn",buff); sleep(1); read(fd,buff,1); printf("parent buff=%sn",buff); } close(fd); exit(0); }
结果
stu@stu-virtual-machine:~/Linux/day09$ ./main parent buff=a child buff=a parent buff=b child buff=bmain.c 打印fd的值
#include#include #include #include #include #include int main() { int fd=open("file.txt",O_RDONLY);//父进程打开 assert(fd!=-1); printf("fd=%dn",fd); pid_t pid=fork(); assert(pid!=-1); if(pid==0) { char buff[32]={0}; read(fd,buff,1); printf("child buff=%sn",buff); sleep(1); read(fd,buff,1); printf("child buff=%sn",buff); } else { char buff[32]={0}; read(fd,buff,1); printf("parent buff=%sn",buff); sleep(1); read(fd,buff,1); printf("parent buff=%sn",buff); } close(fd); exit(0); }
结果:fd=3
stu@stu-virtual-machine:~/Linux/day09$ ./main fd=3 parent buff=a child buff=b parent buff=c child buff=d
PCB里边有文件表—结构体数组(fork后父进程的文件表是什么样子子进程就是什么样子):记录打开的文件
一个进程启动起来,至少打开三个文件:
文件描述符总是一个非负数,fd至少是3
open之后得到以下:
file.txt这块是指针 浅拷贝
磁盘上的文件都有唯一的id值:ls -i
第一种情况先open再fork
由图可以看出parent child打印abcd的原因
第二种情况先fork再open
用户空间、内核空间 系统调用和库函数的区别书第五章
替换进程exec 系列
execl execlp execle 库函数
execv execvp 库函数
(上边5个都调用下边这个系统调用)
execve 系统调用
Linux 产生新进程: fork+exec
执行两次 ps -f
stu@stu-virtual-machine:~/Linux/day09$ ps -f UID PID PPID C STIME TTY TIME CMD stu 2412 2402 0 14:14 pts/0 00:00:00 bash stu 2419 2412 0 14:14 pts/0 00:00:00 ps -f stu@stu-virtual-machine:~/Linux/day09$ ps -f UID PID PPID C STIME TTY TIME CMD stu 2412 2402 0 14:14 pts/0 00:00:00 bash stu 2425 2412 0 14:14 pts/0 00:00:00 ps -f
ps -f的ppid都是bash的pid,bash把自己fork复制一份再exec替换成ps -f(系统中的新进程都是这么来的 eg: ./main)
test.c#include#include #include #include #include #include int main() { printf("test pid=%dn",getpid()); execl("/usr/bin/ps","ps","-f",(char*)0); printf("exec errn"); exit(0); }
execl执行成功没有返回值,没成功继续执行原代码
结果
stu@stu-virtual-machine:~/Linux/day09$ ./test test pid=3071 UID PID PPID C STIME TTY TIME CMD stu 2412 2402 0 14:14 pts/0 00:00:00 bash stu 3071 2412 0 14:42 pts/0 00:00:00 ps -f
man 3 exec
execlint execl(const char* path, const char * arg,...,);
path:新替换的程序的路径名称(eg.which ps)
arg :传给新程序主函数的第一个参数,一般为程序的名字
arg 后面是剩余参数列表,参数个数可变,必须以空指针作为最后一个参数
execlpint execlp(const char* file, const char * arg,...,);
自己去找ps的位置
execlp("ps","ps","-f",(char*)0);execle
int execle(const char* path, const char * arg,...,char* const envp[]);
传环境变量
int main(int argc,char*argv[],char*envp[]) { printf("test pid=%dn",getpid()); execle("/usr/bin/ps","ps","-f",(char*)0,envp); printf("exec errn"); exit(0); }execv
int execv(const char * path, char* const argv[]);
可以写一个char* myargv[10]={“ps”,"-f"};保存
int main(int argc,char*argv[],char*envp[]) { printf("test pid=%dn",getpid()); //execl("/usr/bin/ps","ps","-f",(char*)0); //execlp("ps","ps","-f",(char*)0); //execle("/usr/bin/ps","ps","-f",(char*)0,envp); char* myargv[10]={"ps","-f"}; execv("/usr/bin/ps",myargv); printf("exec errn"); exit(0); }execvp
int execvp(const char * file, char* const argv[]);
eg.
execvp("ps",myargv);execve
int execve(const char * path, char* const argv[],char* const envp[]);
最终test.c
int main(int argc,char*argv[],char*envp[]) { printf("test pid=%dn",getpid()); //execl("/usr/bin/ps","ps","-f",(char*)0); //execlp("ps","ps","-f",(char*)0); //execle("/usr/bin/ps","ps","-f",(char*)0,envp); char* myargv[10]={"ps","-f"}; //execv("/usr/bin/ps",myargv); //execvp("ps",myargv); execve("/usr/bin/ps",myargv,envp); printf("exec errn"); exit(0); }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)