linux进程!!父子进程fork、vfork、退出、wait(&status)、waitpid、execl/lp/v/vp族函数、system(* commad)、popen(*cmd,“r/w“)

 通过getpid获取当前进程号

sys 

pid = 0;交换进程,起着进程调度、资源分配作用

pid = 1;init进程, 系统初始化 譬如界面,

exit():函数exit()“立即”终止调用进程、进程中任何开的文件都被关闭;、进程的任何子进程被进程继承,

wait(&status)等待退出状态、整体长退出用WEXITSTAYUS(status);

waitpid(pid,&status,WNOHANG);//子进程pid,状态值、不挂起WNOHANG

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


int main()
{
        pid_t pid;
        pid_t pid2;
        pid_t retpid;

        pid = getpid();    //获取当前pid
        printf("befer pid:%d\n",pid);

        retpid = fork();   //把fork的pid返回给retpid 如果大于0 就是当前进程 等于0是子进程
        pid2 = getpid();
        printf("after pid:%d\n",pid2);
        if(pid == pid2){   //第一次的两个pid相等在父进程中,第二次不等在子进程中
                printf("this is father pid:%d,retpid:%d\n",getpid(),retpid);
        }
        else{
                printf("this is child pid:%d,retpid:%d\n",getpid(),retpid);
        }
        return 0;
}

 存储空间分配

 

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main()//创建进程不断输入 输入为1 产生一个子进程 父进程什么都不干 让子进程干活
{
        int data;
        pid_t pid;

        while(1){
                printf("qing shu ru data\n");
                scanf("%d",&data);
                if(data == 1){
                        pid = fork();
                        if(pid > 0){        //父进程

                        }
                        else if(pid == 0){    //子进程不断打印
                                while(1){
                                        printf("this is child pid:%d\n",getpid());
                                        sleep(2);
                                }
                        }
                }
                else{
        //              printf("shu ru de  bu shi 1\n");
                }
        }

        return 0;

 vfork使用方法,用exit退出、break退出会打乱cnt

#include <unistd.h>
#include <stdlib.h>
#incldue <stdio.h>

int main()  //vfork 会先执行子进程 且共用一块内存 会改变数据的值用exit退出 否则破坏cnt值
{
        pid_t pid;
        int cnt = 0;
        pid = vfork();

        if(pid > 0){
                while(1){
                        printf("this is the father pid:%d\n",getpid());
                        sleep(2);
                        printf("this is father cnt:%d\n",cnt);
                }
        }
        else if(pid == 0){        //先执行子进程
                while(1){
                        printf("this is the child pid:%d\n",getpid());
                        sleep(2);
                        cnt++;
                        printf("cnt=%d\n",cnt);
                        if(cnt == 5){
                                exit(-1);    //退出子进程 去执行父进程
                        }
                }
        }
        return 0;
}

 10中  进程退出:正常、异常退出

正常退出:main中return、调用exit(0)-----标准c库 会对数据处理保存后再退出,

_exif/Exit数据直接退出、线程执行结束---进程结束退出、调用函数pthread_

异常退出:调用abrt、ctel+c、线程取消

进程退出 :使用同一段退出代码,该代码段--是关闭相应进程的 打开描述符。关闭后并释放内存

父进程通过子进程退出的返回状态判断是否正常退出、活做了多少用wait卡住状态 跟vfork有点类似

//wait等待退出的用法 wait(&status),WEXITSTATUS(status)、exit(5)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()    
{
        pid_t pid;
        int cnt = 0;
        pid = fork();    //产生一个子进程 用wait等待
        int status = 10;   //当status的值和exit退出值相等时说明 子进程正常结束
//             pid_t wait(int *status);

        if(pid > 0){                          //父进程等待 子进程结束wait取status地址等待  
                int num = wait(&status);       //wait(null)也等待 但是不关系子进程退出状态
                printf("wait num = %d\n",num); //wait返回值num是子进程的pid号
                printf("fther wait status = %d\n",WEXITSTATUS(status)); //判断status与                                                                                        
                                                                        //exit是否相等
                while(1){
                        printf("this is the father pid:%d\n",getpid());
                        sleep(2);
                }
        }
        else if(pid == 0){
                while(1){
                        printf("this is the child pid:%d\n",getpid());
                        sleep(2);
                        cnt++;
                        printf("cnt=%d\n",cnt);
                        if(cnt == 5){
                                exit(5);  //子进程 先执行结束退出 把5传递给wait的status
                        }
                }
        }
        return 0;
}

 僵尸进程:父进程不收集子进程退出状态 

孤儿进程:子进程还未结束 父进程先结束了

waitpid(pid,&status,WNOHANG);用法和孤儿进程

//僵尸进程 和孤儿进程
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>


int main()
{
        pid_t pid;
        pid = fork();
        int cnt = 0;
        int status = 10;
//       pid_t waitpid(pid_t pid, int *status, int options);
        if(pid > 0){               //子进程还没结束父进程就先结束了
                printf("this is father pid:%d\n",getpid());
        }
        else if(pid == 0){        //子进程
                while(1){ //子进程用getppid打印父进程 第二次之后为1 用init函数收集父进程状态
                            //init收留 防止产生更多的孤儿进程
                        printf("this is child pid:%d\nfathepid:%d\n",getpid(),getppid());
                        cnt++;
                        printf("cnt = %d\n",cnt);
                        if(cnt == 5){
                                exit(5);
                        }
                        sleep(2);
                }
        }

        return 0;
}

exec族函数:

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);

//exex族函数 调用成功直接运行族函数中的可执行文件,不反回,错误返回-1
//exexl exexlp execvp
#include <stdio.h>
#include <unistd.h>

int main()
{
//       int execl(const char *path, const char *arg, ...);//注意exexl四个参数
        if(execl("./echarg","echarg","aa",NULL) == -1){    //成功直接执行 调用的可执行文件
                printf("exec error!!\n");                  //错误返回-1
                perror("why:");
        }
        printf("mei you diao yong chenggong\n");
        return 0;
}



int main()
{
//       int execl(const char *path, const char *arg, ...);
        if(execl("/bin/ps","ps","-aux",NULL) == -1){    //exexl参数(路径、文件名、传参、                                                                                        
                                                        //    NULL结尾)
                printf("exec error!!\n");
                perror("why:");
        }
        printf("mei you diao yong chenggong\n");
        return 0;
}


int main()
{
//       int execl(const char *path, const char *arg, ...);
        if(execlp("date","date",NULL,NULL) == -1){      //exexlp不用加路劲 PATH已近声明
                printf("exec error!!\n");
                perror("why:");
        }
        printf("mei you diao yong chenggong\n");
        return 0;
}

int main()
{
//       int execvp(const char *file, char *const argv[]);
        char *argv[] = {"data",NULL,NULL};
        if(execvp("date",argv) == -1){        //execvp两个参数 封装
                printf("exec error!!\n");
                perror("why:");
        }
        printf("mei you diao yong chenggong\n");
        return 0;
}



int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);

 
int execvpe(const char *file, char *const argv[],char *const envp[])
int execle(const char *path, const char *arg,..., char * const envp[]);

exec族函数函数的作用:

我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。

返回值:
  exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。
参数说明:
path:可执行文件的路径名字
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录

main函数中fork打开子进程,在子进程中exrcl("./changeData","changeData","test.txt",NULL)

直接写到if里面不够灵活,因为我们只能把子进程的程序代码粘贴过来执行,这样必须知道源代码,太长了也不好控制,比如希望子进程执行ls -a,这样是不行的,因为ls的源代码没有这样ls放在子进程里面就实现不了,

此时就是用exec族函数,可以直接把一个编译好的可执行程序,直接加载运行

//fork创建子进程 在子进程中用execl函数执行可执行文件
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
int main()
{
        pid_t pid;
        int data;
        while(1){
                scanf("%d",&data);//不要加换行
                printf("please input!\n");

                if(data == 1){    //输入为1 创建子进程
                        pid = fork();
                        printf("password");
                        if(pid > 0){
                                wait(NULL);//只要有等待就不会成为僵尸进程
                        }
                        else if(pid == 0){ //在子进程中调用changeData函数 传过去txt文件修改
                                execl("./changeData","changeData","config.txt",NULL);

                        }
                }

        }
        return 0;
}

/*
int main()    //execl执行的changeData程序
{
        int fd;
        char *readBuf;
        fd = open("./config.txt",O_RDWR|O_CREAT,0600);
        int size = lseek(fd,0,SEEK_END);
        lseek(fd,0,SEEK_SET);
        readBuf = (char *)malloc(sizeof(char)*size + 8);
        read(fd,readBuf,size);

        char *p = strstr(readBuf,"LENG=");
        if(p == NULL){
                printf("mei zhao dao !\n");
        }
        p = p+strlen("LENG=");
        *p = '5';
        p = p+sizeof(char);
        *p = '5';

        lseek(fd,0,SEEK_SET);
        write(fd,readBuf,strlen(readBuf));
        close(fd);
}

*/                                                                                                                

system函数使用方法

#include <stdio.h>
#include <stdlib.h>

int main()
{                                  //system和exex函数大致相同
                                   //成功返回进程pid 不能返回时返回127 失败返回-1
        if(system("ls -l") == -1){ //先执行system函数 结束后 返回继续执行其他
                printf("erro\n");
                perror("why:\n");
        }
        printf("da yin cheng gong\n");

        return 0;
}

 popen函数用法

//pipe exec system一般用于子进程中执行可以执行文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
                             //pipe是流(只能r/w) 返回文件类型 用fread把里面内容读出来 并打印
//       FILE *popen(const char *command, const char *type);
        FILE *fp;
        char str[1024] = {0};                   //用于存放读取文件
        fp = popen("ps -aux|grep ./a.out","r");  //pipo可以获取输出结果 返回文件类型
//       size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
        int n_fread = fread(str,1,1024,fp);      //流 用fread获取内容
        printf("n_read:%d  str:%s\n",n_fread,str);//打印
        fclose(fp);
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值