- 1. 主函数参数介绍
- 2. printf函数输出问题
- 3. 复制进程fork
- (1)fork方法
- (2)fork练习
- 4. 僵死进程及处理方法
- 5. 操作文件的系统调用
- (1)文件的读写
- (2)完成对普通文件的复制
- 6. 系统调用和库函数的区别
- 7. 进程替换
int main( int argc, char* argv[], char* envp[])
(1) argc 参数个数
(2) argv 参数内容
(3) envp 环境变量
代码执行结果
printf 函数并不会直接将数据输出到屏幕,而是先放到缓冲区中,只有以下三种情况满足,才会输出到屏幕。
1) 缓冲区满
2) 强制刷新缓冲区 fflush
3) 程序结束时
#include#include #include #include #include int main(int argc,char* argv[],char* envp[]) { char *s=NULL; int n=0; pid_t pid=fork(); assert(pid!=-1); if(pid==0) { s="child"; n=3; } else { s="parent"; n=7; } for(int i=0;i (2)fork练习 #include#include #include #include #include int main(int argc,char* argv[],char* envp[]) { for(int i=0;i<2;i++) { fork(); printf("An"); } exit(0); } 打印6个A
#include#include #include #include #include int main(int argc,char* argv[],char* envp[]) { for(int i=0;i<2;i++) { fork(); printf("A"); } exit(0); } 打印8个A
没有n:把缓冲区放满或者程序结束时才打印#include#include #include #include #include int main(int argc,char* argv[],char* envp[]) { fork()||fork(); printf("An"); exit(0); } 输出3个A
4. 僵死进程及处理方法子进程先于父进程结束,父进程没有调用 wait 获取子进程退出码
解决方法:父进程通过调用wait()完成
#include#include #include #include #include #include int main(int argc,char* argv[],char* envp[]) { char *s=NULL; int n=0; pid_t pid=fork(); assert(pid!=-1); if(pid==0) { s="child"; n=3; } else { s="parent"; n=7; int val=0; wait(&val); if(WIFEXITED(val))//判断程序是不是正常结束 { printf("child exit code=%dn",WEXITSTATUS(val));//提前退出码 } } for(int i=0;i 5. 操作文件的系统调用 (1)文件的读写 #include#include #include #include #include #include int main() { int fw=open("a.txt",O_WRONLY|O_CREAT,0600); assert(fw!=-1); write(fw,"hello",5); close(fw); int fr=open("a.txt",O_RDONLY); assert(fr!=-1); char buff[128]={0}; int n=read(fr,buff,127); printf("buff=%s,n=%dn",buff,n); close(fr); } (2)完成对普通文件的复制
#include6. 系统调用和库函数的区别#include #include #include #include #include int main(int argc,char* argv[]) { if(argc!=3) { printf("arg errn"); return 0; } char *filename=argv[1]; char *newfilename=argv[2]; int fdr=open(filename,O_RDONLY); int fdw=open(newfilename,O_WRONLY|O_CREAT,0600); if(fdr==-1||fdw==-1) { printf("open file failedn"); return 0; } char buff[512]={0}; int n=0; while((n=read(fdr,buff,512))>0) { write(fdw,buff,n); } close(fdr); close(fdw); } 区别: 系统调用的实现在内核中,属于内核空间,库函数的实现在函数库中,属于用户空间。
每个进程都有自己的文件表,程序只要启动起来,默认情况下打开了三个文件:标准输入、标准输出和标准错误输出。#include#include #include #include #include #include int main(int argc,char* argv[]) { int fd=open("file.txt",O_RDONLY); assert(fd!=-1); pid_t pid=fork(); assert(pid!=-1); char buff[32]={0}; if(pid==0) { read(fd,buff,1); printf("buff=%sn",buff); sleep(1); read(fd,buff,1); printf("buff=%sn",buff); } else { read(fd,buff,1); printf("buff=%sn",buff); sleep(1); read(fd,buff,1); printf("buff=%sn",buff); } } 执行结果:
7. 进程替换
write()一定会直接打到屏幕上,而printf()会先存在缓冲区,等程序结束时再系统调用write()函数。
fork 和 exec 联合使用创建一个全新的进程
#include#include #include #include #include int main(int argc,char* argv[],char* envp) { char* myenvp[10]={"STR=hello"}; char* myargv[10]={"ps","-f"}; printf("main pid=%dn",getpid()); //execl 执行成功不返回,直接从新程序的主函数开始执行,只有失败才返回错误码 //execl("/usr/bin/ps","ps","-f",(char*)0); //execlp("ps","ps","-f",(char*)0); //execle("/usr/bin/ps","ps","-f",(char*)0,envp); //execv("/usr/bin/ps",myargv); //execvp("ps",myargv); execve("/usr/bin/ps",myargv,envp); printf("execl errn"); }



