精华内容
下载资源
问答
  • 用多进程实现bash

    2013-03-06 08:35:00
    思路:先创建一个父进程,然后在父进程创建一个子进程,而在子进程中调用exec函数族,父进程所要做的只是等待子进程的结束,然后再次循环等待用户输入下一条命令。注:因为要模拟的是bash,所以在一条命令执行完成...

    思路:先创建一个父进程,然后在父进程中创建一个子进程,而在子进程中调用exec函数族,父进程所要做的只是等待子进程的结束,然后再次循环等待用户输入下一条命令。注:因为要模拟的是bash,所以在一条命令执行完成了后,执行命令的进程结束了,但是bash并没有结束(即不能在父进程中调用exec函数族,否则父进程也会结束,不符合实际),而是等待刚才输入的命令结束后,再次提示用户输入下一条命令,直到用户输入了exit为止。

    代码:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    
    #define N 64
    
    int main(int argc, char *argv[])
    {
        char buf[N] = {0};   //定义并初始化一个字符串数组
        char *arg[N];     //定义一个指针数组
        pid_t pid;
        int i = 0, j;
    
        while (1)
        {
            printf("linux@ubuntu:~$");
            fgets(buf, N, stdin);//ls -l -a   //等待用户从键盘输入,回车后将输入的内容写到buf,包括 \n,
    										  //此时,buf数组中以\0结尾,\0 前面是 \n,显然 \n 不是命令
            buf[strlen(buf)-1] = '\0';        //将buf数组中的\0前面的那个\n用\0进行覆盖
            if (strcmp(buf, "exit") == 0)     //看输入的是否为exit,注:没有对空格进行处理
                break;
    
            if ((pid = fork()) == -1)         //创建子进程
            {
                perror("fork");
                exit(-1);
            }
            if (pid == 0)
            {
    		/*
    			下面是利用strtok函数将buf数值进行解析,把命令和参数分别解析出来,strtok函数的使用参见
    			C语言函数大全:下面是部分内容
    			头文件:#include <string.h>
    
    			定义函数:char * strtok(char *s, const char *delim);
    
    			函数说明:strtok()用来将字符串分割成一个个片段. 参数s 指向欲分割的字符串, 参数delim 则为分割字符串,当strtok()在参数s 的字符串中发现到参数delim 的分割字符时则会将该字符改为\0 字符. 在第一次调用时,strtok()必需给予参数s 字符串, 往后的调用则将参数s 设置成NULL. 每次调用成功则返回下一个分割后的字符串指针.
    
    			返回值:返回下一个分割后的字符串指针, 如果已无从分割则返回NULL.
    
    			范例
    			#include <string.h>
    			#include <stdio.h>
    			int main(void)
    			{
    				char s[] = "ab-cd : ef;gh :i-jkl;mnop;qrs-tu: vwx-y;z";
    				char *delim = "-: ";
    				char *p;
    				printf("%s ", strtok(s, delim));
    				while((p = strtok(NULL, delim)))
    					printf("%s ", p);
    				printf("\n");
    				return 0;
    			}
    			执行结果:
    			ab cd ef;gh i jkl;mnop;qrs tu vwx y;z //-与:字符已经被\0 字符取代
    
    		*/
                arg[i] = strtok(buf, " ");      
                do
                {
                    ++i;
                    arg[i] = strtok(NULL, " ");
                }while(arg[i] != NULL);
    
                for (j = 0; j < i; j++)
                    printf("%s\n", arg[j]);
    
            //    char * arg[] = {"ls", "-l", "-a", NULL};
                if (-1 == execvp(arg[0], arg)) //在子进程中调用execvp函数,子进程的三段被替换
                {
                    perror("execvp");
                    exit(-1);
                }
            }
            else
                wait(NULL);  //父进程等待子进程就是,即等待argv[0]中指向的命令执行完
        }
    
        return 0;
    }
    

    转载于:https://www.cnblogs.com/pengdonglin137/archive/2013/03/06/2945378.html

    展开全文
  • bash进程与wait,sleep区别

    千次阅读 2015-08-09 23:54:34
    bash中,使用后台任务来实现任务的“多进程化”。在不加控制的模式下,不管有多少任务,全部都后台执行。也就是说,在这种情况下,有多少任务就有多少“进程”在同时执行。我们就先实现第一种情况: 实例一:...
    在bash中,使用后台任务来实现任务的“多进程化”。在不加控制的模式下,不管有多少任务,全部都后台执行。也就是说,在这种情况下,有多少任务就有多少“进程”在同时执行。我们就先实现第一种情况:

    实例一:正常情况脚本

     #!/bin/bash

    for ((i=0;i<5;i++));do
           {
                  sleep 3;echo1>>aa&& echo "done!"
           } 
    done
    wait
    cat aa|wc -l
    rm aa
     

    这种情况下,程序顺序执行,每个循环3s,共需15s左右。

     $ time bash test.sh 
    done!
    done!
    done!
    done!
    done!
    5

    real    0m15.030s
    user    0m0.002s
    sys     0m0.003s
     

    实例二:“多进程”实现

     #!/bin/bash

    for ((i=0;i<5;i++));do
           {
                  sleep 3;echo1>>aa&& echo "done!"
           } &
    done
    wait
    cat aa|wc -l
    rm aa
     
    这个实例实际上就在上面基础上多加了一个后台执行&符号,此时应该是5个循环任务并发执行,最后需要3s左右时间。

    $ time bash test.sh 
    done!
    done!
    done!
    done!
    done!
    5

    real    0m3.011s
    user    0m0.002s
    sys     0m0.004s
     
    效果非常明显。

    这里需要说明一下wait的左右。wait是等待前面的后台任务全部完成才往下执行,否则程序本身是不会等待的,这样对后面依赖前面任务结果的命令来说就可能出错。例如上面wc-l的命令就报错:不存在aa这个文件。

    wait命令的官方解释如下:
           wait [n]
                Wait for the specified process and return itstermination status.  n may be a process ID or a  job specification; if a job spec is given, allprocesses in that job's pipeline are waited for.  If n is not given, all currently activechild processes are waited for, and the return status iszero.  If  n specifies  a non-existent process  or job,the return status is 127.  Otherwise, thereturn status is the exit status of the last processor job waitedfor.
     
    以上所讲的实例都是进程数目不可控制的情况,下面描述如何准确控制并发的进程数目

     #!/bin/bash
    # 2006-7-12, by wwy
    #-----------------------------------------------------------------------------------
    # 此例子说明了一种用wait、read命令模拟多线程的一种技巧
    # 此技巧往往用于多主机检查,比如ssh登录、ping等等这种单进程比较慢而不耗费cpu的情况
    # 还说明了多线程的控制
    #-----------------------------------------------------------------------------------

    function a_sub { # 此处定义一个函数,作为一个线程(子进程)
    sleep 3 # 线程的作用是sleep 3s
    }


    tmp_fifofile="/tmp/$$.fifo"
    mkfifo $tmp_fifofile     # 新建一个fifo类型的文件
    exec 6<>$tmp_fifofile     #将fd6指向fifo类型
    rm $tmp_fifofile


    thread=15 # 此处定义线程数
    for((i=0;i<$thread;i++));do 
    echo
    done >&6 #事实上就是在fd6中放置了$thread个回车符


    for ((i=0;i<50;i++));do #50次循环,可以理解为50个主机,或其他

    read -u6 
    # 一个read-u6命令执行一次,就从fd6中减去一个回车符,然后向下执行,
    #fd6中没有回车符的时候,就停在这了,从而实现了线程数量控制

    { # 此处子进程开始执行,被放到后台
          a_sub&& { # 此处可以用来判断子进程的逻辑
          echo "a_sub is finished"
          } ||{
          echo "sub error"
         }
         echo >&6 #当进程结束以后,再向fd6中加上一个回车符,即补上了read -u6减去的那个
    } &

    done

    wait # 等待所有的后台子进程结束
    exec 6>&- # 关闭df6
    exit 0


    sleep 3s,线程数为15,一共循环50次,所以,此脚本一共的执行时间大约为12秒
    即:
    15x3=45, 所以 3 x 3s = 9s
    (50-45=5)<15, 所以 1 x 3s =3s 
    所以 9s + 3s = 12s

    $ time ./multithread.sh >/dev/null
    real       0m12.025s
    user       0m0.020s
    sys        0m0.064s


    而当不使用多线程技巧的时候,执行时间为:50 x 3s = 150s。

    此程序中的命令mkfifo tmpfile和linux中的命令mknod tmpfile p
    效果相同。区别是mkfifo为POSIX标准,因此推荐使用它。该命令创建了一个先入先出的管道文件,并为其分配文件标志符6。管道文件是进程之间通信的一种方式,注意这一句很重要
    exec 6<>$tmp_fifofile     #将fd6指向fifo类型
    如果没有这句,在向文件$tmp_fifofile或者&6写入数据时,程序会被阻塞,直到有read读出了管道文件中的数据为止。而执行了上面这一句后就可以在程序运行期间不断向fifo类型的文件写入数据而不会阻塞,并且数据会被保存下来以供read程序读出。


    wait是bash内嵌命令,见man bash,sleep不是bash的built-in命令。

    wait command stop script execution until all jobs running inbackground have terminated or until the job number or process idspecified as an option terminates

    wait%1 or 
    
    wait $PID 
    
    wait ${!}
    

    wait ${!} means "to wait till the last background process iscompleted" ($! being the PID of the lastbackground process)

    Sleep

    add delay for a specified amount of time.

    sleep NUMBER[SUFFIX]
    sleep 5 (sleep five seconds)
    
    再如:

    #!/bin/bash
    log=/tmp/test.sh.log
    ./test.sh &
    pid=$!

    while :
    do
        wait $pid
        time=$(date)

        echo "$time process is down ">$log
       ./test.sh&
        pid=$!

    done


    这段代码是重复不断执行test.sh,等test完成之后输出时间。

    展开全文
  • bash shell和进程

    2018-03-27 12:41:00
    创建子shell,在原进程的上启动新的脚本,但是它会把老shell的环境清理掉,所以,它从原shell中什么也不继承,在一个干净的环境中执行新的脚本。执行完之后退出当前的shell。 2 source builtin 不创建子shell,...

    1 exec builtin

    不创建子shell,在原进程的上启动新的脚本,但是它会把老shell的环境清理掉,所以,它从原shell中什么也不继承,在一个干净的环境中执行新的脚本。执行完之后退出当前的shell。

    2 source builtin

    不创建子shell,在原进程上执行source的脚本。脚本的执行环境和原shell的一样。

    3 bash filename或者./filename

    创建子shell。

    子shell可以从父shell继承环境变量、当前工作目录、已经打开的文件标识符、标准输入、标准输出和标准错误输出。

    除了环境变量以外的变量都是不能继承的。

    4 $(xxx)和`xxx`,命令替换

    子 shell中执行。

     5 查看shell

    echo  $0

    转载于:https://www.cnblogs.com/hustdc/p/8656822.html

    展开全文
  • Linux进程编程实践——进程概念、进程... Linux下的进程描述——task_struct二、fork创建进程2.1 获取进程标识符查看进程Q1:为什么要知道一个进程的PID以及它父进程的PID呢?2.2 fork创建进程Q1:如何理解进程创建?Q

    一、进程的基本概念

    在学习进程之前我们需要理解和区分两个概念:程序和进程。

    1.1 程序 VS 进程

    <1> 什么是程序?

    程序是完成特定任务的一系列指令集合。
    举个栗子,下面这段代码就是一个程序

    #include<stdio.h>
    #include<unistd.h>
    
    int main()
    {
      while(1)
      {
      	printf("hello world\n");
        sleep(1);
      }
      return 0;
    }
    

    我们编译好后把它运行起来:
    在这里插入图片描述

    <2> 什么是进程?

    • 用户的角度来看:进程是程序的一次执行过程
    • 操作系统的核心来看:进程是操作系统分配的内存、CPU时间片等资源的基本单位。

    进程是资源分配的最小单位,每一个进程都有自己独立的地址空间执行状态。像Linux这样的多任务操作系统能够让许多程序同时运行,每一个运行着的程序就构成了一个进程
    我们另开一个窗口,使用ps命令就可以查看刚才运行的程序以及它所构成的进程
    在这里插入图片描述

    <3> 进程和程序的区别

    • 进程是动态的,程序是静态
    • 进程的生命周期是相对短暂的,而程序是永久的。
    • 一个进程只能对应一个程序,一个程序可以对应多个进程

    1.2 进程数据结构(描述进程)

    <1> 操作系统的进程描述——PCB

    进程的静态描述由三部分组成:PCB、有关程序段和该程序段对其进行操作的数据结构集。

    • 进程控制块(Process Control Block, PCB):用于描述进程情况及控制进程运行所需的全部信息。
    • 代码段:是进程中能被进程调度程序在CPU上执行的程序代码段。
    • 数据段:一个进程的数据段,可以是进程对应的程序加工处理的原始数据,也可以是程序执行后产生的中间或最终数据

    <2> Linux下的进程描述——task_struct

    • 在Linux中描述进程的结构体叫做task_struct。它是PCB的一种。
    • task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信

    task_ struct内容分类

    • 标示符: 描述本进程的唯一标示符,用来区别其他进程。
    • 状态: 任务状态,退出代码,退出信号等。
    • 优先级: 相对于其他进程的优先级。
    • 程序计数器: 程序中即将被执行的下一条指令的地址。
    • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
    • 上下文数据: 进程执行时处理器的寄存器中的数据。
    • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
    • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
    • 其他信息

    二、fork创建进程

    2.1 获取进程标识符与查看进程

    进程最知名的属性就是进程号(processID,PID)和它父进程号(parent processID,PPID)。

    • PID和PPID都是非零的整数
    • 一个PID唯一标识一个进程。
    • 一个进程创建的另一个新进程称为子进程。相反地,创建子进程的进程称为父进程
    • 所有进程追溯其祖先最终都会落到进程号为1的进程身上,这个进程叫init进程Init进程是linux内核启动后第一个执行的进程。
    • Init引导系统,启动守护进程并且运行必要的程序。

    通过调用getpid()获取进程id,调用getppid()获取父进程id,举个栗子:

    #include<stdio.h>
    #include<unistd.h>
    
    int main()
    {
      printf("子进程pid:%d\n",getpid());
      printf("父进程ppid:%d\n",getppid());
    
      return 0;
    }
    
    

    运行结果:
    在这里插入图片描述
    我们可以使用ps,top等命令查看系统进程,也可以通过下述操作查看
    在这里插入图片描述

    Q1:为什么要知道一个进程的PID以及它父进程的PID呢?

    PID常见的用法之一就是创建唯一的文件或目录名。
    另一种的用途是把PID写入日志文件做为日志消息的一部分。

    2.2 fork创建进程

    对于Linux系统,我们运行man fork命令来认识fork
    在这里插入图片描述

    • 包含头文件 <unistd.h>
    • 函数功能:创建一个子进程
    • 函数原型:pid_t fork(void);
    • 参数:无参数。
    • 返回值:
      • 如果成功创建一个子进程,对于父进程来说返回子进程ID
      • 如果成功创建一个子进程,对于子进程来说返回值为0
      • 如果为-1表示创建失败
        在这里插入图片描述

    掌握了函数的用法后,我们通过实例来掌握并理解fork函数和进程创建

    #include<stdio.h>
    #include<unistd.h>
    
    int main()
    {
      printf("未调用fork打印一遍\n");
      
      fork();
      printf("调用fork打印两遍,父进程ID:%d , 进程ID:%d \n",getppid(), getpid());
      sleep(1);
      return 0;
    }
    
    

    通过上述代码我们调用fork函数创建进程,可以发现fork()语句之后printf语句被执行了两次
    在这里插入图片描述
    我们可以更加形象的理解进程间的关系:

    bash进程(id:23920)——爷爷

    第一个输出进程(id:31987),与bash进程为父子关系——儿子

    第二个输出进程(id:31988),与第一个输出进程为父子关系——孙子

    Q1:如何理解进程创建?

    博客1.2节中介绍了进程的数据结构由PCB+代码段+数据段,而Linux中的PCB是由task_struct代替的,创建一个进程在Linux中,我们目前可以认为需要三部分构成

    • task_struct
    • 数据段
    • 代码段
      但是创建一个子进程确只需要创建task_struct和数据段,代码段是和父进程共享的,这在一定程序上节省了空间。
      在这里插入图片描述

    Q2:如何理解父子进程执行顺序?

    fork系统调用之后,父子进程将交替执行。

    Q3:如何理解fork一次调用,两次返回(两个返回值)?

    首先问题的本质是:两次返回,是在各自的进程空间中返回的
    在Q1中我们了解到子进程和父进程各有自己的内存空间 (fork函数:代码段、数据段、堆栈段、PCB进程控制块的复制)。父进程调用fork函数,子进程也会调用,且返回值都会存入到自己的数据段中,我们通过一个程序来深刻理解两次返回。

    #include<stdio.h>
    #include<unistd.h>
    
    int main()
    {
      
      int ret =  fork();
      if(ret < 0)
      {
        printf("进程创建失败!\n");
      }
      else if(0 == ret)
      {
        printf("我是儿子(id:%d),fork返回值:%d\n",getpid(),ret);
      }
      else
      {
        printf("我是父亲(id:%d),fork返回值:%d\n", getpid(),ret);
      }
      sleep(1);
      return 0;
    }
    
    

    运行结果
    在这里插入图片描述
    由结果可看出,成功创建一个子进程,对于父进程来说返回子进程ID:4451,对于子进程来说返回值为0

    展开全文
  • Bash编程】之 协作进程coproc

    千次阅读 2019-03-04 19:10:40
    shell中的协作进程coprocess是指...”一样,不同的是,协作进程与其父进程间有双向的管道,提供了一种便利的通信途径。 协作进程命令格式如下: coproc [NAME] command [redirections] 上述命令用于创建一个名为N...
  • 我们在维护服务器的时候,经常遇到,有些大量的日志文件,但是不知道是哪个脚本、程序、进程创建的,我们在压缩、删除日志文件的同时,也必须要在脚本里修改设置,让其自动的维护它们所创建的文件。那么我们如何通过...
  • 1什么是进程进程是一个执行中的程序 ...进程有很多数据维护:进程状态/进程属性 所有进程属性采用的一个树形结构体维护 ps -a//所有进程 ps -aue //有效进程  进程状态:(man ps
  • bash shell实现并发多进程操作

    千次阅读 2018-07-03 09:50:20
    项目里代码都是用其实现),bash shell(运维利器),c(acm专用),这里面能实现多线程的貌似只有c,但是我c只是用来学习和实现算法和数据结构,因此工作中我想要模拟多进程并发操作,就只能依靠bash shell脚本了...
  • i am 1 child 出现了`1`次 = (2^0) i am 2 child 出现了`2`次 = (2^1) i am 3 child 出现了`4`次 = (2^2) i am 4 child 出现了`8`...I am parent 出现了`31`次 = (2^0) + (2^1) + (2^2) + (2^3) + (2^4) 所有子进程之和
  • Linux下创建进程

    万次阅读 2018-11-03 22:17:55
    创建进程在Linux的下是由父进程来完成的,创建完成的新进程是子进程。子进程有三种执行顺序的可能性: 父进程和子进程并发执行; 子进程先执行,父进程等待子进程执行完毕。 父进程先执行,子进程后执行。 另外...
  • 今天介绍进程进程的管理,子进程创建以及进程资源的回收 首先什么是进程? 答:进程是程序的实例。程序是静态的,是存放在硬盘上的,程序运行起来就形成了进程。程序从磁盘到内存里之后就形成了进程进程又分为...
  • 进程的基本流程进程创建fork初识写时拷贝进程等待进程等待必要性进程等待的方法(wait和waitpid)waitwaitpid获取进程status进程替换进程替换原理进程替换函数进程替换函数命名理解进程终止进程常见退出方法exit退出...
  • linux创建守护进程

    2017-03-15 19:16:24
    1、创建进程,父进程退出此时,子进程为孤儿进程终端脱离的部分关系 2、在子进程创建新会话 => setsid()此时,子进程为新建会话组的组长,  彻底脱离于原bash会话组的关系 3、改变当前目录为根目录 =>...
  • 在入侵检测的过程中,进程创建监控是必不可少的一点,因为攻击者的绝大多数攻击行为都是以进程的方式呈现,所以及时获取到新进程创建的信息能帮助我们快速地定位攻击行为。 本文将介绍一些常见的监控进程创建的方式...
  • bash启动过程

    2010-01-20 20:22:23
    用户登录过程剖析 Bash Bash 用户在登录成功后...1.交互式登录:即是在登录过程中由登录进程创建Bash进程,如login进程启动的Bash,ssh登录时,sshd创建的子进程。 2.非登录的交互式:如在图形界面中,启动的...
  • 何为守护进程进程组 / 组长进程 / 会话 / 会话首进程 、守护进程创建步骤 、创建守护进程程序示例
  • bash脚本提交后台运行For example, I want to spawn many ssh background processes in one bash script: 例如,我想在一个bash 脚本中生成许多ssh后台进程: for i in `cat ./all-hosts` do ssh $i "ifconfig | ...
  • Bash百宝箱】协作进程coproc

    千次阅读 2016-09-14 09:29:25
    ”一样,不同的是,协作进程与其父进程间有双向的管道,提供了一种便利的通信途径。 协作进程命令格式如下:coproc [NAME] command [redirections]上述命令用于创建一个名为NAME的协作进程,如
  • 摘要这将创建一个子外壳,因此两个进程正在运行:line=$(ps aux | grep [m]yscript)这不会创建子外壳.因此,myscript.sh仅运行一个进程:ps aux | grep [m]yscript示范让我们稍微修改一下脚本,以便将流程和子流程PID...
  • 进程篇:循环创建N个子进程

    千次阅读 2018-05-14 00:00:00
    进程篇:循环创建N个子进程 标签:fork();N个子进程 从前面的进程篇——fork()可以了解到fork函数会创建进程和子进程,并且他们在执行的时候,怎么来控制说是先创建进程,还是先创建进程呢?其实根据...
  • 写一个bash版的守护进程

    千次阅读 2016-09-18 13:39:39
    一、守护进程的定义在linux或者unix操作系统中,守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。二、守护进程的用途在日常使用当中,有些linux...
  • 在写一些bash批处理脚本的时候,我们通常希望能够快速的声明新function,并在不影响主进程的情况下执行。我常用的解决方案是 #!/bin/bash func() { cd /tmp echo func中的pwd: $PWD exit } echo 运行func...
  • Bash中的进程替换(process substitution)

    千次阅读 2013-06-27 20:57:00
    进程替换(process substitution)是Bash中的一个有意思的语法。  语法规则:使用 ()  很多有关Bash的文档对这条规则并没有解释得很清楚,在这里综合部分搜索后的结果,得出个人理解: 首先举一个例子,看一下...
  • pid_t pid = fork();
  • 进程的概念和创建方式(理论)(多道程序设计)在某一个瞬间,CPU只能运行一个进程,但在一秒钟期间,它可能运行多个进程,这样就产生并行的错觉。 —— 伪并行进程(process): 就是一个正在执行程序的实例,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 115,344
精华内容 46,137
关键字:

创建的进程与bash进程