- 复制进程:fork()
- 习题一:
- 习题二
- 习题三
- 习题四
- 僵死进程
- test.c
- 解决方法wait
- 法一
- 法二
- 文件描述符
- 文件操作
- open
- read
- write
- close
- open.c
- 写一个复制图片
写时拷贝:提高了fork复制的效率
习题一:int main()
{
for(int i=0;i<2;i++)
{
fork();
printf("An");
}
}
打印6个A
父进程 i=0 fork A; i=1 fork A;
右子进程(i=0 此时从fork后开始执行)A; i=1 fork A
左下子进程(i=1)A;
右下子进程(i=1)A;
习题二int main()
{
for(int i=0;i<2;i++)
{
fork();
printf("A");
}
}
打印8个A,原本父进程打了一个A,复制的时候,缓存区也会存着A给子进程
父进程 i=0 fork A(缓冲区); i=1 fork A;
右子进程(i=0 此时从fork后开始执行)A(存在缓冲区); i=1 fork A
左下子进程(i=1)父缓冲区A+A;
右下子进程(i=1)右子缓冲区A+A;
习题三int main()
{
fork()||fork();
printf("An");
}
打印3个A
C语言中||:他会先算前一部分,如果前一部分为真,他将停止运算,如果为假,他才会算第二部分,你这里第一部分就为真了,第二部分当然也就不会算了。
父进程 fork()||fork(); 只执行第一个fork(fork>0),执行后杀死,打印了一个A
子进程 fork()||fork(); 被杀死的第一个fork(==0),因此执行第二个fork(复制出一个子进程),打印一个A
子进程的子进程 fork()||fork(); 被杀死的第一个fork(==0),被杀死第二个fork(==0),打印一个A
习题四int main()
{
fork()&&fork();
printf("An");
}
打印三个A
C语言中:&&且操作 ,&&为界将表达式分为两部分,他会先算前一部分,如果前一部分为假,他将停止运算,如果为真,他才会算第二部分,你这里第一部分就为假了,第二部分当然也就不会算了。
父进程 fork()&&fork(); 执行第一个fork(fork>0),生成子进程1,执行第二个fork,生成子进程2,打印一个A
子进程1 fork()&&fork(); 被杀死的第一个fork(fork==0),不执行第二个fork,打印了一个A
子进程2 fork()&&fork(); 被杀死的第一个fork(fork>0),被杀死的第二个fork(fork==0),打印一个A
僵死进程僵死(僵尸)进程:子进程先结束,父进程没有调用wait获取子进程的退出码,子进程就变成了僵死进程
(PCB没有被删掉)
test.c#include#include #include #include #include int main() { int n=0; char*s=NULL; pid_t pid=fork(); assert(pid!=-1); if(pid==0) { n=3; s="child"; } else { n=10; s="parent"; } for(int i=0;i 后台运行,ps查看->可显示僵死进程
stu@stu-virtual-machine:~/Linux/day08$ ./test& [1] 3669 stu@stu-virtual-machine:~/Linux/day08$ s=parent s=child s=child s=parent ps PID TTY TIME CMD 2550 pts/0 00:00:00 bash 3669 pts/0 00:00:00 test 3670 pts/0 00:00:00 test 3671 pts/0 00:00:00 ps stu@stu-virtual-machine:~/Linux/day08$ s=child s=parent s=parent s=parent ps PID TTY TIME CMD 2550 pts/0 00:00:00 bash 3669 pts/0 00:00:00 test 3670 pts/0 00:00:00 test解决方法wait 法一3672 pts/0 00:00:00 ps stu@stu-virtual-machine:~/Linux/day08$ s=parent s=parent s=parent s=parent s=parent 获得退出码(man 3 wait)
#includepid_t wait(int *stat loc) test.c
#include#include #include #include #include #include int main() { int n=0; char*s=NULL; pid_t pid=fork(); assert(pid!=-1); if(pid==0) { n=3; s="child"; } else { n=10; s="parent"; int val=0; wait(&val); printf("exit_code=%dn",val); } for(int i=0;i 结果
stu@stu-virtual-machine:~/Linux/day08$ ./test s=child s=child s=child exit_code=768 s=parent s=parent s=parent s=parent s=parent s=parent s=parent s=parent s=parent s=parent768>>8 = 3
法二判断程序正常结束 获得退出码
test.c
#include#include #include #include #include #include int main() { int n=0; char*s=NULL; pid_t pid=fork(); assert(pid!=-1); if(pid==0) { n=3; s="child"; } else { n=10; s="parent"; int val=0; wait(&val); if(WIFEXITED(val))//判断程序正常结束 { printf("exit_code=%dn",WEXITSTATUS(val));//提取退出码 } } for(int i=0;i 结果
stu@stu-virtual-machine:~/Linux/day08$ ./tests=childs=childs=childexit_code=3s=parents=parents=parents=parents=parents=parents=parents=parents=parents=parent父进程先于子进程结束不是僵死进程
因为子进程在父进程结束后被init接收,init pid=1
test.c
#include#include #include #include #include #include int main() { int n=0; char*s=NULL; pid_t pid=fork(); assert(pid!=-1); if(pid==0) { n=7; s="child"; } else { n=3; s="parent"; } for(int i=0;i 结果(以前init接管,ppid=1,现在不一定)
stu@stu-virtual-machine:~/Linux/day08$ ./tests=parent,pid=3849,ppid=2550s=child,pid=3850,ppid=3849s=parent,pid=3849,ppid=2550s=child,pid=3850,ppid=3849s=child,pid=3850,ppid=3849s=parent,pid=3849,ppid=2550s=child,pid=3850,ppid=3849stu@stu-virtual-machine:~/Linux/day08$ s=child,pid=3850,ppid=1816s=child,pid=3850,ppid=1816s=child,pid=3850,ppid=1816文件描述符 文件操作Linux open read write close 系统调用(在内核中实现)
C语言 fopen fread fwrite fclose 库函数(/usr/lib/c.so 在库中实现)
Windows 分 文本文件 和 二进制文件,Linux不区分
man 2 openman 2 readman 2 writeman 2 closeopenint open(const char* pathname, int flags);//用于打开一个已存在的文件int open(const char* pathname, int flags,mode_t mode);//用于新建一个文件,并设置访问权限pathname:将要打开的文件路径和名称
flags : 打开标志,如 O_WRonLY 只写打开
O_RDonLY 只读打开
O_RDWR 读写方式打开
O_CREAT 文件不存在则创建
O_APPEND 文件末尾追加
O_TRUNC 清空文件,重新写入
mode: 权限 如:“0600”----读写4+2
返回值:为文件描述符
readssize_t read(int fd, void* buf, size_t count);fd 对应打开的文件描述符
buf 存放数据的空间
count 计划一次从文件中读多少字节数据
返回值:为实际读到的字节数
writessize_t write(int fd, const void* buf,size_t count);fd 对应打开的文件描述符
buf 存放待写入的数据
count 计划一次向文件中写多少数据
closeint close(int fd);fd 要关闭的文件描述符
open.c写
#include#include #include #include#include #include #include int main(){ int fd=open("file.txt",O_WRONLY|O_CREAT,0600); assert(fd!=-1); write(fd,"hello",5); close(fd);} 结果
stu@stu-virtual-machine:~/Linux/day08$ ./openstu@stu-virtual-machine:~/Linux/day08$ lsfile.txt main main.c open open.c test test.cstu@stu-virtual-machine:~/Linux/day08$ cat file.txthello stu@stu-virtual-machine:~/Linux/day08$读
#include#include #include #include #include #include #include int main() { int fd=open("file.txt",O_RDONLY); assert(fd!=-1); char buff[128]={0}; int n=read(fd,buff,127);//n==0,表示读到了文件末尾 //只读127防止溢出 printf("buff=%sn",buff); close(fd); } 结果
stu@stu-virtual-machine:~/Linux/day08$ ./open buff=hello写一个复制图片open.c
#include#include #include #include #include #include #include int main() { int fdr=open("1.jpg",O_RDONLY); int fdw=open("5.jpg",O_WRONLY|O_CREAT,0600); if(fdr==-1||fdw==-1) { return 0; } char buff[1024]={0}; int n=0; while((n=read(fdr,buff,1024))>0) { write(fdw,buff,n); } close(fdr); close(fdw); } 结果
stu@stu-virtual-machine:~/Linux/day08$ ./open stu@stu-virtual-machine:~/Linux/day08$ ls 5.jpg main open test file.txt main.c open.c test.c stu@stu-virtual-machine:~/Linux/day08$ ls -l 总用量 76 -rw------- 1 stu stu 0 11月 30 17:53 5.jpg -rw------- 1 stu stu 5 11月 30 17:34 file.txt -rwxrwxr-x 1 stu stu 16736 11月 30 15:29 main -rw-rw-r-- 1 stu stu 322 11月 30 15:29 main.c -rwxrwxr-x 1 stu stu 16872 11月 30 17:52 open -rw-rw-r-- 1 stu stu 743 11月 30 17:52 open.c -rwxrwxr-x 1 stu stu 17016 11月 30 16:43 test -rw-rw-r-- 1 stu stu 664 11月 30 16:43 test.c



