首页 > 其他分享 >第六周学习笔记

第六周学习笔记

时间:2022-10-09 15:44:47浏览次数:38  
标签:学习 int pid 笔记 第六周 getpid printf 进程 include

第3章 Unix/Linux进程管理

摘要

  • Unix/Linux中的进程管理;
  • 阐述了多任务处理原则;
  • 介绍了进程概念;
  • 说明多任务处理、上下文切换和进程处理的各种原则和方法。
  • 讲解进程的执行模式进行了,如何通过中断、异常和系统调用从用户模式转换到内核模式;
  • 描述用于进程管理的Unix/Linux系统调用,包括forkwatexec和exit;阐明了父进程与子进程之间的关系,包括进程终止和父进程等待操作之间关系的详细描述;
  • 解释如何通过INIT进程处理孤儿进程,包括当前Linux中的 subreaper进程,并通过示例演示了subreaper进程;接着,详细介绍了如何通过exec更改进程执行映像,包括execve系统调用命令行参数和环境变量;
  • 解释了I/O重定向和管道的原则及方法,并通过示例展示了管道编程的方法;

多任务处理

多任务处理指的时同时进行几项独立活动的能力。多任务处理是通过在不同任务之间多路复用CPU执行时间来实现的。
如果切换速度够快,就会给人一种通知执行所有任务的错觉。这种逻辑并行性称为“并发”

进程的概念

在操作系统中,任务也成为进程。进程是对映像的执行。
操作系统内核将一系列执行视为使用系统资源的单一实体。
系统资源包括内存空间、I/O设备以及最重要的CPU时间。PROC结构体包含了某个进程的所有信息。

多任务处理系统

简称MT

type.h文件

type.h文件定义了系统常熟和表示进程的简单PROC结构体。
ts.s文件
在32位GCC汇编代码中可实现进程上下文切换

queue.c文件

可实现队列和链表操作函数。
enqueue()函数按优先级将PROC输入队列中。在优先级队列中,具有相同优先级的进程按照FIFO的顺序排序。
dequeue()函数可返回从队列或链表中删除的第一个元素。
printList()函数可打印链表元素。

t.c文件

定义MT系统数据结构、系统初始化代码和进程管理函数

多任务处理系统代码介绍

1.虚拟CPU:MT系统在Linux下编译链接为

gcc -m32 t.c ts.s

然后运行a.out。

2.init():当MT系统启动时,main()函数调用init()以初始化系统
3.p0调用kfork()来创建优先级为1的子进程P1,并将其输入就绪队列。
4.tswitch():tswitch()函数实现进程上下文切换。
5.kfork():kfork()函数创建一个子任务并将其输入readyQueue中
6.boby():为便于演示,所有创建的任务都执行同一个boby()函数
7.空闲任务P0:P0的特殊之处在于它在所有任务中具有最低的优先级
8.运行多任务处理器(MT)系统: 在Linux下,输入

gcc -m32 t.c s.s

编译链接MT系统并运行所得到的a.out

进程同步

一个操作系统包含许多并发进程,这些进程可以彼此交互。进程同步是指控制和协调进程交互以确保其正确执行所需要的各项规则和机制。最简单的进程同步工具是休眠和唤醒操作
睡眠模式
当某进程需要某些当前没有的东西时,例如申请独占一个存储区域、等待用户通过标准输入来输入字符等,它就会在某个事件值上进入休眠状态,该事件值表示休眠的原因
唤醒模式
多个进程可能会进入休眠状态等待同一个事件,这是很自然的,因为这些进程可能都需要同一个资源,例如一台当前正处于繁忙状态的打印机。在这种情况下,所以这些进程都将休眠等待同一个事件值。

进程终止

正常终止
进程调用exit(value),发出_exit(value)系统调用来执行在操作系统内核中的kexit(value)
异常终止
进程因某个信号而异常终止
在这两种情况下,当进程终止时,最终都会在操作系统内核中调用 kexit()

Unix/Linux中的进程

进程来源

操作系统内核会强行创建PID=0初始进程,然后,系统执行初始进程P0,然后,挂载一个跟文件系统,最后,P0复刻出一个子进程P1

INIT和守护进程

P1运行时,将执行映像更改为init程序,P1通常被称为init进程,P1的大部分子进程都是用来提供系统服务的,称为守护进程

登录进程

每个终端上一个,用于用户登录

sh进程

用户登录成功时,LOGIN进程会获取用户的gid和uid,从而成为用户的进程

进程的执行模式

  • 内核模式(Kmode)
  • 用户模式(Umode)

    Umode进程只能通过以下三种方式加入Kmode:
  • 中断
  • 陷阱
  • 系统调用

进程管理的系统调用

fork()

Usage:  int pid = fork();

fork()创建子进程并返回子进程的pid,如果fork()失败则返回-1

示例:演示fock.c

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

int main()
{
    int pid;
    printf("THIS IS %d MY PARENT =%d\n",getpid(),getppid());
    pid = fork();
    if(pid){
        printf("THIS IS PROCESS %d CHILD PID= %d\n",getpid(),pid);
    }
    else {
        printf("this is process %d parent= %d\n",getpid(),getppid());
    }
}

进程终止

正常终止

当内核中的某个进程终止时,他会将_exit(value)系统调用中的值记录为进程PROC结构体中的退出状态。并通知他的二父进程并使该进程成为僵尸进程。父进程课通过系统调用找到僵尸子进程,获得其pid和退出状态
pid=wait(int *status)

异常终止

当某进程遇到异常时,他会陷入操作系统内核。内核的异常处理程序将陷阱错位类型转换为一个幻数,称为信号,将信号传递给进程,时进程终止。用户可以使用命令kill -s signal_numeber pid向通过pid识别的目标发送信号

等待子进程终止

int pid = wait(int *status)

示例:演示等待和退出系统调用

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <wait.h>
 
 int main(){
    int pid ,status;
    pid = fork();

    if(pid){
        printf("PARENT %d WAITS FOR CHILD %d TO DIE\n",getpid(),pid);
        pid = wait(&status);
        printf("DEAD CHILD =%d, status=0x%04x\n",pid,status);
    }else {
        printf("DEAD CHILD=%d dies by exit(VALUE)\n",getpid());
        exit(100);
    }
    return 0;
 }

Linux中的subreaper进程

prctl(PR_SET_CHILD_SUBREAPER);

示例:演示Linux中的subreaper进程

#include <stdio.h>
#include <unistd.h>
#include <wait.h>
#include <sys/prctl.h>

int main()
{
    int pid, r, status;
    printf("mark process %d as a aubreaper\n",getpid());
    r = prctl(PR_SET_CHILD_SUBREAPER);
    pid = fork();
    if (pid){
        printf("subreaper %d child=%d\n", getpid(), pid);
        
        while(1){
        pid = wait(&status);
        if(pid>0)
            printf("subreaper %d waited a ZOMBIE= %d\n", getpid(), pid);
        else 
            break;
        }
    }
    else{
        printf("child %d parent= %d\n",getpid(),(pid_t)getppid());
        pid = fork();
        if(pid){
            printf("child=%d start: grandchild=%d\n",getpid(),pid);
            printf("child=%d EXIT : grandchild=%d\n",getpid(),pid);
        }
        else {
            printf("grandchild=%d start: myparent=%d\n",getpid(),getppid());
            printf("grandchild=%d EXIT : myparent=%d\n",getpid(),getppid());
        }
    }
}

环境变量

各环境变量定义为:关键字=字符串
重要环境变量:

SHELL=/bin/bash
TERM=xterm
USER=kcw
PATH=/usr/1oca1/bin:/usr/bin:/bin:/usr/local/games:/usr/games:./
HOME= / home /kcw
  • SHELL:指定将解释任何用户命令的sh。
  • TERM:指定运行sh时要模拟的终端类型。
  • USER:当前登录用户。
  • PATH:系统在查找命令时将检查的目录列表。
  • HOME:用户的主目录。在 Linux 中,所有用户主目录都在/home中。
    在sh会话中,可以将环境变量设置为新的(字符串)值,如:
    HOME= / home / newhome
    可通过EXPORT命令传递给后代sh,如expoert HOME

I/O重定向

文件流和文件描述符

sh进程又三个用于终端I/O的文件流:stdin(标准输入)、stdout(标准输出)、stderr(标准错误)

文件流I/O和系统调用

当进程执行库函数

scanf("%s", &item);

会试图从stdin文件输入一个(字符串)项,指向FILE结构体

管道

管道是用于进程交换数据的单向进程件通信通道。管道有一个读取端和一个写入端。

Unix/Linux中的管道编程

int pd[2];
int r = pipe(pd);

管道操作的系统模型

示例:演示管道操作

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

int pd[2],n,i;
char line[256];

int main()
{
    pipe(pd);
    printf("pd=[%d, %d]\n",pd[0], pd[1]);
    if(fork()){
        printf("parent %d close pd[0]\n",getpid());
        close(pd[0]);
        while(i++ < 10){
            printf("parent %d writes to pipe\n",getpid());
            n = write(pd[1], "I AM YOUR PAPA", 16);
            printf("parent %d wrote %d bytes to pipe\n",getpid(), n);
        }
        printf("parent %d exit\n", getpid());
    }
    else{
        printf("child %d close pd[1]\n", getpid());
        close(pd[1]);
        while(1){
            printf("child %d reading from pipe\n",getpid());
            if ((n = read(pd[0], line, 128))){
                line[n]=0;
                printf("child read %d bytes from pipe: %s\n", n, line);
            }
            else 
                exit(0);
        }
    }
}

管道命令处理

在Unix/Linux中,命令行cmd1 | cmd2,sh将通过一个进程运行cmd1,并通过另一个进程运行cmd2,他们通过一个管道连接在一起,因此cmd1的输出变为cmd2的输入

命令管道

命令管道又叫FIFO
1.在sh中,通过mknod命令创建一个命令管道:

mknod mypipe p

2.或在c语言中发出mknod()系统调用

int r = mknod("mypipe",s_IFIFP,0);

3.进程可像访问普通文件一样发个文命名管道。

问题:在测试示例fork()时出现问题

implicit declaration of function ‘fork’ [-Wimplicit-function-declaration]

解决方法:通过使用man找到fork的头文件
man fork
其他出现头文件问题可以用相同方法解决。

标签:学习,int,pid,笔记,第六周,getpid,printf,进程,include
From: https://www.cnblogs.com/yycyhyhf/p/16769927.html

相关文章

  • mysql中set和enum枚举类型插入值和索引比较--笔记
    set,enum的数据类型都是字符串类型的对象,其中set最多可以包含64个元素,并且可以任意取到集合中的元素。而enum则是只能取到集合中的木一个元素,最多包含65536个元素,也就是说se......
  • let、const命令(学习阮一峰ES6记录)
    1.let命令ES6新增let命令,作用和var类似,用来声明变量,但是let只能在所在代码块(区域)中使用。例:1{2leta=2;3varb=3;4}5console.log(a)//aisn......
  • ArrayList源码学习
    arraylist1、总体关系图  1.1:Serializable接口这是一个空接口,只有实现了这个接口的对象才可以进行序列化。然后这个序列化id是为了保证反序列化成功也就是在运......
  • Delphi 经典游戏程序设计40例 的学习 例33 点的生存竞争
     unitR33;interfaceusesWindows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,ExtCtrls,StdCtrls;typeTDotDt=r......
  • 2022-2023-1 20221415 《计算机基础与程序设计》第六周学习总结
    2022-2023-120221415《计算机基础与程序设计》第六周学习总结作业信息这个作业属于哪个课程<班级的链接>(2022-2023-1-计算机基础与程序设计)这个作业要求在哪......
  • 转置原理学习笔记
    正如EI所言啊,转置原理不是无中生有创造算法,而是建立了一些问题之间的转化机制。问题形式:考虑一个\(n\timesm\)的矩阵\(A\),我们有一个算法:输入长度为\(m\)的向量......
  • CPM学习
    CPM学习    CPM4与CPM5区别:      CPM5只有QDMA需要16个GTY                       TheCo......
  • python的OS模块学习笔记-1
    OS模块是python和操作系统进行交互的一个接口,它提供许多操作文件及文件夹的函数。1,通过getcwd()函数获取当前文件所在路径。importospath=os.getcwd()print(path)......
  • 学习ELK的资料
     自己对日志分析挖掘处理感兴趣,然后自己在学,没有找到太好的视频,都比较零散,或者有的只是讲Elastic,对于ELK的概念,原理不是很清楚,所以自己在网上也有遇到好的文章,讲的非常清......
  • SQLCookbook 学习笔记 前言
    许多人以一种马马虎虎的态度在使用SQL,根本没有意识到自己掌握着多么强大的武器。本书的目的是打开读者的视野,看看SQL究竟能干什么。一鳞半爪从数据库中检索数据看似是一件容......