程序是存储在磁盘介质上的编译过的二进制文件
进程是程序跑起来的状态
程序是死的,进程是活的
进程是正在执行的程序的一个实例
malloc函数从内存的堆中分配储存
静态变量(通常是所说的程序中的全局变量)会使得线程化的程序不安全,除非保证各个线程访问时是互斥的!!
pid每个进程都有一个id和一个父进程id
获取进程pid/father pid getpid/getppid
就绪的进程就是非阻塞的
阻塞态不会直接去运行
阻塞时不会占用cpu
进程可以通过调用fork函数来创建,调用进程称为父进程
fork函数在子进程中返回0
#include<stdio.h>
#include<unistd.h>
int main(){
int pid;
printf("before fork()...\n");
if((pid = fork()) < 0) perror("fork");
if(pid == 0) printf("In child\n");
else{
sleep(1);
printf("In parent\n");
}
printf("end fork\n");
return 0;
}
#include<stdio.h>
#include<unistd.h>
int main(){
int pid;
printf("before fork()...");
if((pid = fork()) < 0) perror("fork");
if(pid == 0) printf("\nIn child\n");
else{
sleep(1);
printf("\nIn parent\n");
}
printf("end fork\n");
return 0;
}
为什么before fork()…输出了两次??
printf()底层是write实现的,行缓冲,当进行到程序的第6行时没有换行
当程序将数据提交给内核时,内核没有看到换行会以为后面还有数据(行缓冲优化)
fork()之后,两个进程的输出缓冲区都有befoe fork,当两个进程的输出缓冲区都读入到换行时进行输出
创建10个子进程
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(){
int pid, x;
for(int i = 1; i <= 10; i++){
if((pid = fork()) < 0){
perror("fork");
continue;
}
if(pid == 0){
x = i;
break;
}
}
printf("x = %d\n", x);
sleep(1);
return 0;
}
wait函数等待某进程结束
父进程可以通过wait函数一直阻塞到子进程结束
wait(NULL)可以等待当前进程任意一个子进程结束
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main(){
int pid;
printf("before fork()...\n");
if((pid = fork()) < 0) perror("fork");
if(pid == 0) printf("In child\n");
else{
wait(NULL);
printf("In parent\n");
}
printf("end fork\n");
return 0;
}
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main(){
int pid;
for(int i = 1; i <= 5; i++){
if((pid = fork()) < 0) perror("fork");
if(pid == 0){
printf("I'm a child\n");
return 0;
}
}
//wait(NULL);
for(int i = 1; i <= 5; i++){
wait(NULL);
}
printf("I'm parent\n");
return 0;
}
只wait了一次 所有parent不一定最后执行,要wait 5次才行
fork()函数创建了调用程序的一份copy,但很多子程序要求执行不同的代码,exec函数提供了新映像覆盖调用进程映像的功能
The exec() family of functions replaces the current process image with a new process image.
用fork-exec方法使子进程执行新程序,父进程执行原程序
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main(){
int pid;
if((pid = fork()) < 0) perror("fork");
if(pid == 0){
execl("/bin/ls", "ls", "-l", NULL);//之后的程序子进程就没有了 execl已经替换了
perror("child failed to exec ls");
return 1;
}
wait(NULL);
return 0;
}
git commit不加-m选项时:
fork()一个子进程,子进程打开一个vim 保存退出后 父进程读取刚刚写的命令继续执行后续命令
task:a.out a.c
打开a.c文件(没有的话创建一个),编辑保存退出后编译这个文件,编译成功后执行,最后退出
************************************************************************/
//task:a.out a.c
//打开a.c文件(没有的话创建一个),编辑保存退出后编译这个文件,编译成功后执行,最后退出
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
int main(int argc, char **argv){
pid_t pid;
char filename[512] = {0};
char o_name[512] = {0};//编译后的文件名称
char f_type[256] = {0};
char cmd[512] = {0};
if(argc < 2){
fprintf(stderr, "Usage: %s filename arg...\n", argv[0]);
return 1;
}
strcpy(filename, argv[1]);
char *sub = NULL;//找到.的位置 逆序找到最后一个.
if((sub = strrchr(filename, '.')) == NULL){
fprintf(stderr, "Not support File type!\n");
return 2;
}
strncpy(o_name, filename, sub - filename);
strcpy(f_type, sub);
if(!strcmp(f_type, ".c")){
strcpy(cmd, "gcc");
}else if(!strcmp(f_type, ".cpp")){
strcpy(cmd, "g++");
}else{
fprintf(stderr, "Not support File type\n");
return 2;
}
if((pid = fork()) < 0){
perror("fork");
return 3;
}
if(pid == 0){
execlp("vim", "vim", filename, NULL);
}
wait(NULL);
if((pid = fork()) < 0){
perror("fork");
return 3;
}
if(pid == 0){
execlp(cmd, cmd, filename, "-o", o_name, NULL);
}
int status;
wait(&status);
//status = 0表示子进程执行成功
if(status == 0){
char exe_cmd[50] = {0};
sprintf(exe_cmd, "./%s", o_name);
execlp(exe_cmd, o_name, NULL);//./a.out
}else{
printf("compile Failed!\n");
return 4;
}
return 0;
}
https://www.cnblogs.com/mickole/p/3187409.html