进程参数 ps -aux 查看进程命令
pid 进程标识号
ppid 父进程的pid
getpid()
pid_t pid=getpid(); 得到进程自己的pid
getppid()
pid_t pid=getppid(); 得到父进程的pid
fork()
返回值 pid_t pid 父进程:>0 返回值为子进程pid 子进程:=0 出错:=-1
fork调用之后,内存中会出现两个一样的进程,只是pid不同
fork调用原则
一次fork调用,就会产生两个一样的进程,这两个进程是父子关系
在父进程当中调用fork,返回子进程的PID
在子进程中调用fork,返回0
对于父进程和子进程,首地址不同,但每个变量的偏移地址相同,子父进程打印出来的是偏移地址
cpu: 地址总线 数据总线 控制总线
cpu寻址是基本地址+偏移地址寻址,所以cpu内部有个基地址寄存器
wait(&status)
退出码 WEXITSTATUS(status)
父进程调用wait阻塞,等待子进程结束后才返回,wait函数的参数是子进程的退出值
pid_t pid = fork();
if (pid > 0) {
int status = 0;
wait(&status);
printf("wait的退出码 %d\n", WEXITSTATUS(status));
} else if (pid == 0) {
sleep(10);
printf("子进程结束");
return 250;
}
return 0;
文件描述符
父进程和子进程共享打开的文件描述符,一定要在fork之前打开
int fd = open("a.txt",O_RDONLY);
pid_t pid = fork();
char buf[1024];
if (pid ==-1) {
printf("forkerr + %s\n", strerror(errno));
exit(0);
}
if (pid > 0) { //父进程
read(fd,buf.sizeof(buf));
printf("%s\n",buf);
pause();
}
if (pid == 0) { //子进程
printf("子进程+%d", getpid());
exit(0);
}
close(fd);
return 0;
exec()
char *args[] = { "/bin/ls", "-l", NULL};
execve("/bin/ls",args,NULL);
execve()第一个参数是执行程序名,第二个是传递给执行程序的main函数的args参数
和system(a 123)区别 : system会创建一个进程 execve的进程空间就被指定的程序占据
execv读取另一个的进程的文件描述符
myexecv.c
int fd = open("a.txt", O_RDONLY);
if (fd == -1) {
printf("error %s\n", strerror(errno));
return -1;
}
char **ss;
ss[0] = "a";
char stmp[10];
memset(stmp,0,sizeof(stmp));
sprintf(stmp,"%d",fd);
ss[1] = stmp;
ss[2] = NULL;
execve("a", ss, NULL); //通过ss传递参数args
a.c
int fd=atoi(args[1]);
char buf[1024];
memset(buf,0,sizeof(buf));
read(fd,buf,sizeof(buf));
printf("%s\n",buf);
return 0;
execv加fork保留原有进程
myexecv.c
pid_t pid;
pid = fork();
int fd = open("a.txt", O_RDONLY);
if (fd == -1) {
printf("error %s\n", strerror(errno));
return -1;
}
if (pid == -1) {
printf("fork err %s", strerror(errno));
}
if (pid > 0) { //父进程
pause();
} else { //子进程
char *ss[3];
ss[0] = "a";
char stmp[10];
memset(stmp, 0, sizeof(stmp));
sprintf(stmp, "%d", fd);
ss[1] = stmp;
ss[2] = NULL;
execve("a", ss, NULL);
}
return 0;