zoukankan      html  css  js  c++  java
  • Linux 多学习过程

    1Linux流程概述

    过程是,一旦运行过程中的程序,他和程序本质上的区别。程序是静态的,他奉命收集指令存储在磁盘上。
    进程是动态的概念。他是执行者的程序,包括进程的动态创建。调度和消亡,是Linux的基本调度单位。
    进程控制块(PCB)是进程的静态描写叙述,包含进程的描写叙述信息。进程的控制信息,以及资源信息
    时间片:他轮流在每一个进程的得到的时间片用完后从进程那里千回控制权

    1.1进程标识

    os会为每个进程分配一个唯一的盛行ID。作为进程的标识号(pid)。还有父进程ID(ppid)
    全部的进程的祖先都是同一个进程init进程,ID为1
    通过getpid(),getppid() 得到进程的pid。ppid
    实例:printf("pid:%d ppid:%d ",getpid(),getppid());

    1.2进程的用户ID与组ID

    进程执行过程中必须有类似于用户的身份,哪个用户就是该用户的身份,就是那个用户的组
    可用getuid(),getgid();获得
    进程还有有效用户ID和有效组ID,缺少的情况下,与真实ID同样,能够用geteuid(),getegid();
    文件权限有S的时候,有效ID是进程的全部者(创建者),否则有效ID就是程序的执行者,与真实ID同样
    ps -aux查看全部用户进程的权限,cpu,和内存的使用情况
    ps -ef 查看用户操作的PID与PPID 与CMD(命令行)

    1.3进程的状态

    运行态。就绪态。等待态

    1.4LInux下的进程结构

    Linux中的进程包括三个段:数据段,代码段,堆栈段
    数据段:(普通数据段)全局变量,常熟(bbs数据段)为初始化的全局变量以及(堆)动态数据分配的数据空间
    代码段:存放程序代码的数据
    堆栈段:子程序的返回地址,子程序的參数。程序的局部变量




    1.5LInux下的进程管理




    进程process:是os的最小单位
    1)ps查看活动进程
    2)ps -aux查看全部进程%cpu。%mem stat状态(S睡眠T暂停R执行Z僵尸)
    3)ps -aux|grep'aa' 查找指定的(aa)进程
    4)ps -ef能够现实父子关系和cmd
    5)top现实前20条的进程。动态改变
    6)./my_add 可能要执行非常长时间。按ctrl+z能够把京城暂停。在执行  bg作业ID 能够将该进程带入后台执行比如:
    [1]+ ./my_add 1 34 &  ,&表示该进程在后台正在执行。
    利用jods能够查看后台任务
    fg作业ID 把后台人物带到前台
    7)kill -9 进程号(PID) 杀掉该进程  ,pkill a 进程名

    2 进程的创建

    Linux下有四类创建子进程的函数:system(),fork(),exec*(),popen();

    2.1system函数

    system函数system括号中面放的是命令,也就是cmd
     样例例如以下:
    #include<iostream>
    #include<stdlib.h>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    int main(int argc,char *argv[]){
    	char cmd[1024]="";
    	for(int i=1;i<argc;i++){
    		strcat(cmd,argv[i]);
    		strcat(cmd," ");
    	}
    	puts(cmd);
    	int ans;
    	ans=system(cmd);
    	printf("%x
    ",ans);
    }
    用system调用其它可运行程序,并输入參数 输入比如: ./main ./my_add  当中my_add计算两个数之和
    当中计算结果在system的返回值高字节上:ret00,所以直接出256
    int main(int argc,char *argv[]){
    	if(argc!=2){
    		printf("failed
    ");
    		return 0;
    	}
    	int left,right;
    	char cmd[1024]="";
    	char line[1024]="";
    	strcat(cmd,argv[1]);
    	strcat(cmd," ");
    	while(printf(">>"),scanf("%d %d",&left,&right)){
    		memset(line,0,sizeof(line));
    		sprintf(line,"%s %d %d",argv[1],left,right);
    		strcpy(cmd,line);
    		int ret;
    		ret=system(cmd);
    		printf("result:%d
    ",ret/256);
    	}
    }

    2.2fork函数

    fork函数在以存在的进程中创建一个新的进程,新的进程作为子进程。原进程为父进程
    父进程的返回值是子进程。子进程的返回值是0.
    fork创建子进程是全然复制父进程,并且缓冲区也复制
    元进程和子京城都从函数fork返回,在各自继续圆形下去。可是元函数的fork返回值
    是子进程的pid。而在子进程中fork返回0,返回-1表示创建失败

    #include<iostream>
    #include<unistd.h>
    #include<stdlib.h>
    #include<stdio.h>
    using namespace std;
    int main(int argc,char *argv[]){
    	pid_t pid;
    	int i=3;
    	printf("hello
    ");
    	pid=fork();
    	fflush(stdout);//儿子复制的时候将缓冲区也复制了,假设没有这句话。上面的hello将出现两便
    	if(pid>0){
    		printf("parents:pid:%u,ret:%u,pp:%u
    ",getpid(),pid,getppid());
    	}
    	else if(pid==0){
    //		sleep(5);
    		printf("child:pid:%u,ret:%u,pp:%u
    ",getpid(),pid,getppid());
    	}
    	printf("bye!
    ");
    }

    2.3exec函数

    exec函数是用exec的第一个參数制定的程序覆盖现有的进程空间。也就是说运行exec族函数之后。他后面的全部代码不再运行
    具体用法 在终端输入man exec
    int execl(const char *path, const char *arg, ...);
    int execlp(const char *file, const char *arg, ...);
    int execle(const char *path, const char *arg,..., char * const envp[]);
    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[]);
    当中path是包括运行文件名称的全路径名。多个參数时。注意后面最后一个參数必须为NULL,arg是可运行文件的命令行參数

    int execl(const char *path, const char *arg, ...);比如:
    if(execl("/home/yang/0820/my_exec/","my_add","3","2",NULL)==-1){
    		perror("execl error");
    	}
    int execlp(const char *file, const char *arg, ...);比如:
    if(execlp("./my_add","my_add","fwef","fwe","fewgeraf",NULL)==-1){
    		perror("execlp error");
    	}
    int execv(const char *path, char *const argv[]);比如:

    char *args[10];
    	args[0]="my_add";
    	args[1]="12";
    	args[2]="23";
    	args[3]=NULL;
    	if(execv("/home/yang/0820/my_exec/my_add",args)==-1){
    		perror("execl:");
    	}

    2.4popen函数(以后补充)

    popen函数类似system函数,与system不同之处在于它使用管道操作,
    原型为#include<stdio.h>

    FILE*popen(const char *command, const char *type);

    int pclose(FILE *stream);

    command为可运行文件的全路径和运行參数。type可选參数为“r” 或“w”
    “w”popen返回的文件流作为新的进程(比如my_add.exe)标准输入流,即stdin
    “r”popen返回的文件流作为新进程的标准输出流 stdout,也就是说popen仅仅改变新进程的标准输入流或者标准输出流
    popen的具体流程:type为“r”,(即command命令的运行结果作为当前进程的输入结果)。调用程序利用popen函数返回FILE*文件流指针。就能够通过经常使用的stdio库如fgets。来读取被调用函数的输出。

    假设type是“w”(即当前的程序的输出结果作为commend命令的输入),调用程序能够用fwrite想调用程序发送数据,而被调用的程序能够在自己的标准输入上读取这些数据

    样例:
    主程序屏幕输出:
    FILE *fp;
    char a[1000];
    char b[1000];
    char cmd[1024]="";
    printf("plseas write
    ");
    fgets(a,1000,stdin);
    sprintf(cmd,"%s %s",argv[1],a);
    fp=popen(cmd,"r");//这个指令cmd为可运行文件的全路经
    fgets(b,1000,fp);
    printf("%s
    ",b);

    新进程屏幕输出:
    FILE *fp;
    char a[1000];
    gets(a);
    fp=popen(argv[1],"w");
    fputs(a,fp);
    pclose(fp);

    3.进程控制与终止

    用fork函数启动一个子进程时。子进程就有了自己的生命独立执行了
    孤儿进程:假设父进程先于子进程退出,子进程就变成了孤儿进程(一般是父进程负责释放子进程的内存空间),此时将自己主动被PID为1的进程(即init)接管。孤儿进程退出后。它的清理工作由祖先进程init自己主动处理
    僵尸进程:子进程退出,系统不会自己主动清理掉子进程的工作环境,必须有父进程调佣wait或waitpid函数来完毕清理工作。假设父进程不做清理工作。一经推出的子进程就会成为僵尸进程,系统中假设僵尸进程过多就会影响系统性能
    函数原型:
    #include<sys/types.h>
    #include<sys/wait.h>
    pid_t wait(int *status);
    pid_t waitpid(pid_t pid,int *status,int options);
    wait函数随机等待一个已经退出的子进程,并返回该子进程的pid
    waitpid等待制定pid的子进程,如火为-1表示等待全部子进程
    status參数是传出參数,存放子进程的退出状态
    options用于改变waitpid的行为,当中最重要的是WNOHANG,它表示不管子进程是否有退出都马上返回
    产生僵尸进程样例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    main()
    {
        pid_t pid = fork();
        if( pid == 0 )
        {
            exit(10);
        }
        else
        {
    			sleep(10);
    
        }
    }
    避免僵尸进程样例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    main()
    {
        pid_t pid = fork();
        if( pid == 0 )
        {
            exit(10);
        }
        else
        {
    			 wait(NULL);    //NULL表示等待全部进程
    			 sleep(10);	//通常要将sleep放在wait的后面,要不然也会出现僵尸进程
        }
    }

    3.2进程的终止

    5种方式终止:
    1) main函数自然返回
    2)调用exit函数
    3)调用_exit函数
    调用abort函数
    接受能导致进程终止的信号ctrl + c 
    exit与_exit差别:exit会处理缓冲区的内容。_exit不会处理缓冲区的内容

    exit_exit函数的原型:

    #include<stdlib.h> //exit的头文件

    #include<unistd.h> //_exit的头文件

    void  exit(int status);

    void_exit(int status);

    status是一个整型的參数,能够利用这个參数传递进程结束是的状态。0表示正常退出,其它数表示出现错误,进程非正常结束








































    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    安装Manjaro KDE 18.04
    nltk 词性解析
    Ubuntu安装Hadoop
    Ubuntu安装JDK
    Python3-Cookbook总结
    linux 条件变量
    多线程编程 ------ 互斥量
    线程相关笔记
    realloc ------ 扩大malloc得到的内存空间
    gcc 消除未使用变量的警告
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4674671.html
Copyright © 2011-2022 走看看