20191324读书笔记6

第三章 Unix/linux进程管理

  • 多任务处理指的是同时进行几项独立活动的能力
  • 进程:在操作系统中,任务也称为进程,执行映像定义为包含代码、数据和堆栈的存储区,进程就是对映像的执行。
  • PROC结构体:在操作系统知识中我们学习过,进程的状态用一个独特的数据结构表示,叫做进程控制块(PCB)。在Liunx中也可以称为PROC结构体。PROC结构体包含某个进程的所有信息。
点击查看PROC结构体
typedef struct proc{
    struct proc *next;    
    int *ksp;            
    int pid;            
    int status;           
    int priority;         
    int  kstack [SSIZE];  
}PROC;

多任务处理系统

  • type.h文件定义了系统常熟和表示进程的简单PROC结构体
点击查看代码
/*********** type.h file ************/
#define NPROC   9
#define SSIZE 1024
// PROC status
#define FREE    0
#define READY   1
#define SLEEP   2
#define ZOMBIE  3
typedef struct proc{
    struct proc *next;
    int *ksp;
    int pid;
    int status;
    int priority;
    int  kstack [SSIZE];
}PROC;
  • ts.s文件在32位GCC汇编代码中可实现进程上下文切换
点击查看代码
#-------------- ts.s file ----------------
       .globl running,scheduler, tswitch
tSwitch:
SAVE:   pushl %eax :
        pushl %ebx
        pushl %ecx
        pushl %edx
        pushl %ebp
        pushl %esi
        pushl %edi
        pushf1
        movl   running, Sebx
        mov1   # esp,4(%ebx)
FIND:   call  scheduler
RESUME: movl    running,8ebx
        movl    4(%ebx),%esp
        popf1
        popl %edi
        popl %esi
        popl %ebp
        popl %edx
        popl %ecx
        popl %ebx
        popl %eax
        ret
# stack contents=|retPC|eax|ebx|ecx|edx|ebp|esi|edi|eflag|
#                  -1   -2  -3  -4  -5  -6  -7  -8   -9
  • queue.c文件可实现队列和链表操作函数。
点击查看代码
/******************************* queue.c file *******************************/
int enqueue(PROC **queue,PROC *p)
{
    PROC *q = *queue;
    if(q == 0 || p->priority> q->priority){
        *queue = p;
        p->next = q;
    }
    else{
        while(g->next && p->priority <= q->next->priority)
            q = q->next;
        p->next = q->next;
        q->next = p;
    }
}
PROC *dequeue (PROC **queue)
{
    PROC *p = *queue;
    if (p)
        *queue =(*queue)->next;
    return p;
}
int printList(char *name,PROC *p)
{
    printf("%s = ",name);
    while(p){
        printf("[8d %d]->",p->pid,p->priority);
        p = p->next;
    }
    printf("NULL\n");
}
  • enqueue()函数按优先级将PROC输入队列中。在优先级队列中,具有相同优先级的进程按照FIFO的顺序排序。
  • dequeue()函数可返回从队列或链表中删除的第一个元素。
  • printList()函数可打印链表元素。
  • t.c文件定义MT系统数据结构、系统初始化代码和进程管理函数
  • 睡眠模式:当进程需要某些当前没有的东西的时候,就会进入休眠状态。
  • 唤醒操作:调用kwakeup()就可以唤醒一个进程。此时,正在休眠的一个程序得到了需要的资源,继续执行其操作。
  • 进程终止:进程完成后,就会终止或死亡。进程会以两种方式终止:1)正常终止:进程自行调用结束函数exit(value)进行终止。2)异常终止:进程因为某个信号而异常终止。终止时,都会调用kexit()。

进程管理中的系统调用

  • fork:在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。
    通过fork返回的值来判断当前进程是子进程还是父进程。
  • exec:用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行。
    因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈段。

SHELL:指定将解释任何用户命令的sh。
TERM:指定运行sh时要模拟的终端类型。
USER:当前登录用户。
PATH:系统在查找命令时将检查的目录列表。
HOME:用户的主目录。在 Linux 中,所有用户主目录都在/home中。

环境变量

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

点击查看代码
*#include <unistd.h>*
*int execl( const char *pathname, const char *arg0, ... /* (char *)0 */ );*
*int execv( const char *pathname, char *const argv[] );*
*int execle( const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[] */ );*
*int execve( const char *pathname, char *const argv[], char *const envp[] );*
*int execlp( const char *filename, const char *arg0, ... /* (char *)0 */ );*
*int execvp( const char *filename, char *const argv[] );*

I/O重定向

  • sh进程有三个用于终端I/O的文件流:stdin(标准输入)、stdout(标准输出)、stderr(标准错误)。其文件描述符分别对应0、1、2。

管道 |

  • 管道是用于进程交换数据的单向进程件通信通道。管道有一个读取端和一个写入端。
  • 管道命令处理:在Unix/Linux中,命令行cmd1 | cmd2,sh将通过一个进程运行cmd1,并通过另一个进程运行cmd2,他们通过一个管道连接在一起,因此cmd1的输出变为cmd2的输入
  • 命令管道:命令管道又叫FIFO。在sh中,通过mknod命令创建一个命令管道:
    mknod mypipe p
    或在c语言中发出mknod()系统调用
    int r = mknod("mypipe",s_IFIFP,0);
    进程可像访问普通文件一样发个文命名管道。

实践

fork.c

运行结果

posted on 2021-10-24 16:20  20191324  阅读(27)  评论(0编辑  收藏  举报