• Linux+cenos+XV6 学习使用记录


    shell脚本并不能作为正式的编程语言,因为它是在linux的shell中运行的,所以称为shell脚本。事实上,shell脚本就是一些命令的集合;

    如何写一个脚本http://vlambda.com/wz_1j5U66jku2.html

    另外在做实验中的方法:

    1)

    2)如果没配置系统路径,在shell-script文件中,可执行文件前要加 ./ 

    ----

    其他实验:

     

     

     

     

    执行成功

     

    查看并杀死相关进程

     

     

    fork():

    创建一个子进程,克隆一份,可以看作完全一样,但共享的只有代码区

    子进程将获得父进程数据空间、堆、栈等资源的相同副本,但不共享;

    fork 函数被成功调用后将安装父进程的样子复制出一个完全相同的子进程。父进程 fork()

    函数结束时的返回值是子进程的 PID 编号。新创建的子进程则也是从 fork()返回处开始执行,

    但不同的是它获得的返回值是 0

    父进程返回子进程PID号,子进程结束返回0;出错只有父进程返回-1,子进程不会被创建

     

     

    两层fork(),创建孙辈进程

     

     

     

    演示父子进程的创建和销毁

     

     

    两下回车两个进程均死亡

     

     

     

     

    补充:

    D 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)

    R 运行(正在运行或在运行队列中等待)

    S 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)

    T 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行

    Z 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)

     

    孤儿进程和僵尸进程

    创建一个演示demo并编译

     

     

    查看进程执行状态:

     


     

     

     

    exec 函数族的函数则可以用新的可执行程序的内容来更新进程影像,从而

    完成“变身”操作

     

    ecve()函数的第一个参数就是想要变成的“新”进程影像(可执行文件),第二个参数

    是命令行参数,第三个变量是环境变量。这里可以看到字进程通过 execve()将自己变身为

    /usr/bin/ls”,因此不再执行与父进程里的代码——即后面的“printf("this printf()will not be

    exec,because …”是没有机会得到执行的。真是的运行结果如所示,可以看到字进程变成了 ls

     

    联系shell 两者使用场景:

    我们在 shell 命令提示符下键入 HelloWorld-getchar 并回车后,shell 首先是 fork()创建出一

    个字进程来(进程映像仍是 shell),然后再利用 exec 函数族的函数变身为 HelloWorld-getchar

    fork() exec 函数族构成了创建新进程的完整操作,如果父子进程功能相同则只用 fork()如果

    父子进程不同则利用 exec 函数族的来实现

     

    创建pthread线程:

    线程概念的引入,将调度执行,资源分配两个属性做了分割;

    不同的执行流首先需要具有不同的程序指针(IP),其次在函数调用上要记录各自

    不同的函数调用栈

     

    在相同的进程映像等基本资源之上,各个线程保留少量资源:各自的执行流的 IP

    (当然包括其他 CPU现场)、各自的用户态堆栈(记录者该执行流的函数调用层次关系等)。

    这些 IP CPU现场和用户态堆栈等信息可以简单笼统地认为记录在进程控制块内,对于 Linux

    而言就是用 struct task_struct 结构体来统一管理本线程的相关资源

    mm_strcut 用来描述一个进程的虚拟地址空间。每个进程只有一个mm_struct结构,在每个进程的task_struct结构中,有一个指向该进程的结构。可以说,mm_struct结构是对整个用户空间的描述

    task_struct结构体是Linux下的进程控制块PCB(可以理解为一种数据结构);PCB里包含着一个进程的所有信息

     

     

    每个进程或线程在内核空间中都会有自己的进程控制块 task_struct,因此在图 2-7 的右上

    角我们绘制了内核空间里的各个进程自己的 task_struct

    但是只有进程才会有独立的内存空间,即用mm_struct 描述的进程内存布局和相应的页表;

    。需要注意各个进程的内核空间部分是相同的,因此任何一个进程进入它内核空间。。无论是进程还是线程,都必须有进程控制块 PCBstruct task_struct),但是线程间共享进程空间因此不需要独立的内存描述

    符(struct mm_struct)以及所辖的内存区域描述符等,也不需要独立的文件描述符或其他资源。

    的内核空间,都可以访问到其他进程的进程控制块 task_strcut 和内存描述符 mm_struct

    Demo:

    Lightweight Process 的缩写,Linux LWP 指代线程

     

     

     

     

     

    线程和进程开销对比:

    比较PCB

    1)第一个demo多进程:

     

     

    1)  第二demo多线程

     

     

    可以看到,线程作为调度执行单位,进程控制块 PCBtask_struct)还是需要的,这是最

    小资源的一部分。因此这方面资源开销对进程和线程都是一样的

     

    对比mm_struct

     

     

    对比vm_area_struct

     

     

     

    这里可以看出来,pthread-100-demo 虽然创建了 100 个线程,但是用于共享进程空间,并

    没有增加一个mm_struct。不过由于每个进程需要一个独立的用户台堆栈,这些堆栈需要一个

    独立的 vm_are_struct 结构体来描述(一个 vm_area_struct 结构体用于描述进程内部的连续、

    相同属性的内存区),因此将会增加 100 vm_area_struct 用于描述线程用户态栈。但是 100

    个进程的话就更多,每个简单的进程至少需要大约 15 vm_area_struct 结构体,100 个进程

    需要增加大约 1500 vm_area_struct。用 cat /proc/slabinfo |grep vm_area_struct 观察 fork-100-

    demo,可以发现新增大约 15xx 左右的使用量

  • 相关阅读:
    hostnamectl set-hostname liuge
    java.io.IOException: Could not locate executable nullinwinutils.exe in the Hadoop binaries.
    基于API和SQL的基本操作【DataFrame】
    DataFrame 转换为Dataset
    RDD转换为DataFrame【反射/编程】
    WordCount程序【Spark Streaming版本】
    基于RDD实现简单的WordCount程序
    easyui禁止下拉框
    JavaScript join() 方法
    JavaScript push() 方法
  • 原文地址:https://www.cnblogs.com/debug-the-heart/p/13816776.html
Copyright © 2020-2023  润新知