【linux系统】unix编程之进程(基础版)

1.base

程序是存储在磁盘介质上的编译过的二进制文件

进程是程序跑起来的状态

程序是死的,进程是活的

进程是正在执行的程序的一个实例

malloc函数从内存的堆中分配储存

静态变量(通常是所说的程序中的全局变量)会使得线程化的程序不安全,除非保证各个线程访问时是互斥的!!

pid每个进程都有一个id和一个父进程id

获取进程pid/father pid getpid/getppid

2.进程状态

【linux系统】unix编程之进程(基础版)

就绪的进程就是非阻塞的

阻塞态不会直接去运行

阻塞时不会占用cpu

3.进程创建fork函数

进程可以通过调用fork函数来创建,调用进程称为父进程

fork函数会复制父进程的内存映像,新进程会收到父进程地址空间的一份copy

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;
}

【linux系统】unix编程之进程(基础版)

#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;
}

【linux系统】unix编程之进程(基础版)

为什么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;
}

4.等待函数wait

wait函数等待某进程结束

父进程可以通过wait函数一直阻塞到子进程结束

wait(NULL)可以等待当前进程任意一个子进程结束

【linux系统】unix编程之进程(基础版)

#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次才行

5.覆盖函数exec

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

上一篇:OSTEP阅读笔记:5-CPU api


下一篇:256-Linux虚拟内存映射和fork的写时拷贝