回顾上节:
父子进程的关系
子进程是父进程的副本
子进程获得父进程的数据段,堆,栈,正文段共享
在fork之后,一般情况下那个会先运行是不确定的,取决于操作系统
练习:
用进程实现文件拷贝
代码如下
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
//./a.out src dest
int main(int argc, const char *argv[])
{
if (argc != 3)
{
printf("Usgae: %s <src> <dest>\n",argv[0]);
return -1;
}
pid_t pid = fork();
int fd_s = open(argv[1],O_RDONLY);
if (fd_s < 0 )
{
perror("open fail");
return -1;
}
int fd_d = open(argv[2],O_WRONLY|O_CREAT|O_EXCL|O_TRUNC,0666);
if (fd_d < 0 )
{
if (errno == EEXIST)
{
//perror("1 open fail");
fd_d = open(argv[2],O_WRONLY);
}else
{
perror("2 open fail");
return -1;
}
}
if (pid == -1)
{
perror("fork fail");
return -1;
}
char buf[1024] = {0};
struct stat st;
stat(argv[1],&st);
int len = st.st_size;
int cnt = 0;
if (pid > 0)
{
while (cnt < len/2)
{
int ret = read(fd_s,buf,sizeof(buf));
cnt += ret;
write(fd_d,buf,ret);
}
}else if (pid == 0)
{
lseek(fd_s,len/2,SEEK_SET);
lseek(fd_d,len/2,SEEK_SET);
while (cnt < len-len/2)
{
int ret = read(fd_s,buf,sizeof(buf));
cnt += ret;
write(fd_d,buf,ret);
}
}
close(fd_s);
close(fd_d);
return 0;
}
进程创建好之后
1.子进程与父进程做的事情差不多 //子承父业
多任务 : 淘宝服务器 程序 ------创建子程序
2.父进程创建出子进程之后,子进程做的事情与父进程完全不同 //自力更生
shell程序 --- bash
exec函数族
作用:
启动(运行)一个新的程序
用一个新的进程的镜像取代(各个段)当前进程的镜像(各个段),但不包括pcb
函数族:
1、int execl(const char *path,const char *arg,.....);
l:list
path:要执行的文件路径 eg:"bin/ls"
arg:要执行的文件的名字 eg:"ls"
....:可执行文件所需要的参数 eg:对于cp指令,就需要原文件和目标文件
2、int execv(const char *path,const char *arg,.....);
V --- vector(向量)
3、int execlp(const char *file,const char *arg,.....);
带p的命令,除了第一个参数与上述不一样之外,其他参数相同。此时不需要写入文件的路径,只需要填入要执行的可执行文件的文件名 //可执行文件必须在系统的/bin目录中
4、int execvp(const char *file, char *const argv[]);
5、int execvpe(const char *file, char *const argv[],char *const envp[]);
env(environment)环境变量
一个一个字符串,只不过这个字符串的前面是,后面是
char *const envp[]:传递你要打印的环境变量
进程的执行
结束方式:
1.正常结束
1)main 中 return
2)exit() //库函数
c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。
注册清理函数(atexit)。
3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。 //系统调用
//4) 主线程退出
//5)主线程调用pthread_exit
2.异常结束
6)abort()
7)signal kill pid
//8) 最后一个线程被pthread_cancle