【av68676164(p18-p20)】进程控制

时间:2020-03-18 12:06:31   收藏:0   阅读:69

4.2.1 进程控制的概念

进程控制的概念

进程创建

功能:创建一个具有制定标识(ID)的进程

参数:进程标识、优先级、进程起始地址、CPU初始状态、资源清单等。

创建进程的过程

进程创建的伪代码

// CPU的状态,内存,优先级
Create(Si, Mi, Pi) {
  // 分配新的PCB
  p = Get_New_PCB();
  // 分配进程的PID
  pid = Get_New_PID();
  // 设置进程的PID
  p->ID = pid;
  // CPU的状态
  p->CPU_State = Si;
  // 内存
  p->Memory = Mi;
  // 优先级
  p->Priority = Pi;
  // 进程状态
  p->Status.Type = "Ready";
  // 进程队列RL:Ready List
  p->Status.List = RL;
  ...;
  // 将进程p插入到就绪队列
  Insert(RL, p);
  // 调度程序
  Scheduler();
}

进程撤销

功能

进程撤销的时机/事件

进程撤销的实现

进程阻塞

功能:停止进程的执行,变为阻塞

阻塞的时机/事件

参数

进程阻塞的实现

进程唤醒

功能:唤醒处于阻塞队列的某一个进程

引起唤醒的时机/事件

参数:被唤醒进程的标识

原语

原语是由若干指令构成具有特定功能的函数

具有原子性,其操作不可分割

进程创建的原语:(同上伪代码),所以进程创建是一个原语

进程控制原语

4.2.2 Windows进程控制

Windows启动EXE程序创建进程的方法

技术分享图片

思考:Windows如何通过编程启动exe程序创建进程?

#include <iostream>
#include <Windows.h>
using namespace std;

const char* NOTEPAD_PATH = "C:/Windows/System32/notepad.exe";

int main() {
    system(NOTEPAD_PATH);
    WinExec(NOTEPAD_PATH, SW_SHOWNORMAL);
    ShellExecute(NULL, (LPCWSTR)L"open", (LPCWSTR)L"notepad.exe", NULL, NULL, SW_SHOWMAXIMIZED);

    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    BOOL ret = CreateProcess(NULL, (LPWSTR)L"notepad.exe", NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi);
   
    return 0;
}

以下三个函数都是对CreateProcess的封装

_DCRTIMP int __cdecl system(
    _In_opt_z_ char const* _Command
);

WinExec(
    _In_ LPCSTR lpCmdLine,
    _In_ UINT uCmdShow
    );

SHSTDAPI_(HINSTANCE) ShellExecuteW(_In_opt_ HWND hwnd, _In_opt_ LPCWSTR lpOperation, _In_ LPCWSTR lpFile, _In_opt_ LPCWSTR lpParameters,
    _In_opt_ LPCWSTR lpDirectory, _In_ INT nShowCmd);

CreateProcess()创建进程

CreateProcessW(
    _In_opt_ LPCWSTR lpApplicationName,     // 可执行程序名
    _Inout_opt_ LPWSTR lpCommandLine,       // [可执行程序名]程序参数
    _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
    _In_ BOOL bInheritHandles,
    _In_ DWORD dwCreationFlags,             // 创建标志(优先级……)
    _In_opt_ LPVOID lpEnvironment,
    _In_opt_ LPCWSTR lpCurrentDirectory,
    _In_ LPSTARTUPINFOW lpStartupInfo,      // 启动信息(进程启动的状态,是否显示窗口……)
    _Out_ LPPROCESS_INFORMATION lpProcessInformation    // 
    );

创建新进程

STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
::CreateProcess((LPWSTR)L"C:/Windows/System32/notepad.exe", (LPWSTR)L"C:/readme.txt", NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi);

结束进程

WINBASEAPI DECLSPEC _NORETURN VOID WINAPI ExitProcess(UINT uExitCode);
WINBASEAPI WINBOOL WINAPI TerminateProcess(HANDLE hProcess, UINT uExitCode);

4.2.3 Linux进程控制

创建进程

pid_t fork(void);

例子:

pid_t pid = fork();
#include <unistd.h>
#include <cstdio>

int main() {
    pid_t pid;
    int count = 0;
    pid = fork();
    printf("This is first time, pid = %d\n", pid);
    printf("This is second time, pid = %d\n", pid);
    count++;
    printf("count = %d\n", count);
    if (pid > 0) {
        printf("This is the parent process,the child has the pid:%d\n", pid);
    } else if (!pid) {
        printf("This is the child Process.\n");
    } else {
        printf("fork failed.\n");
    }
    printf("This is third time, pid = %d\n", pid);
    printf("This is fouth time, pid = %d\n", pid);
    return 0;
}

运行结果

This is first time, pid = 1174
This is second time, pid = 1174
count = 1
This is the parent process,the child has the pid:1174
This is third time, pid = 1174
This is fouth time, pid = 1174
This is first time, pid = 0
This is second time, pid = 0
count = 1
This is the child Process.
This is third time, pid = 0
This is fouth time, pid = 0

Process finished with exit code 0

思考:下面程序在屏幕上将输出什么内容

int main() {
  fork();   // 子进程是父进程的复制,父子进程都输出了
  printf("Hello World!\n");
 
  return 0;
}

输出结果:

父子进程在并发运行

技术分享图片

思考:下面程序运行结果是什么

#include <unistd.h>
#include <cstdio>

int main() {
    pid_t pid;
    pid = fork();
    if (pid == 0) {
        printf("Hello World!\n");
    } else if (pid > 0) {
        printf("How are you!\n");
    }

    return 0;
}

输出结果:

技术分享图片

父子进程谁先输出不确定

fork返回值pid**

Upon successful completion, fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent process. Otherwise, a value of -1 is returned to the parent process, no child process is created, and the global variable errno is set to indicate the error.

修改:增加输出pid,运行结果如下

PID of current Process is : 1609
How are you!    // 父进程
PID of current Process is : 0
Hello World!    // 子进程

Process finished with exit code 0

fork函数的实现

在文件/kernel/fork.c中

int do_fork(unsigned long clone_flags,
             unsigned long stack_start,
             unsigned long stack_size,
             int __user *parent_tidptr,
             int __user *child_tidptr) {
  struct task_struct *p;
  // 分配无力页面存放task_struct结构和内核空间的堆栈
  p = alloc_task_struct();
  // 把当前进程的task_struct结构中所有内容拷贝到新进程中
  *p = *current;
  // 判断用户进程数量是否超过了最大限制,否则不许fork
  if ((&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur) {
    goto bad_fork_free;
  }
  // 子进程状态设TASK_UNINTERRUPTIBLE
  p->state = TASK_UNINTERRUPTIBLE;
  // 拷贝进程的所有信息
  copy_files(clone_flags, p);
  copy_fs(clone_flags, p);
  copy_mm(clone_flags, p);
  // 进程创建后与父进程链接起来形成一个进程组
  list_add(&p->thread_group, &current->thread_group);
  // 唤醒进程,将其挂入可执行队列等待被调度
  wake_up_process(p);s
}

进程执行与父进程不同的功能

exec函数簇(包括若干函数)

// unistd.h
int  execl(const char * __path, const char * __arg0, ...) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
int  execle(const char * __path, const char * __arg0, ...) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
int  execlp(const char * __file, const char * __arg0, ...) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
int  execv(const char * __path, char * const * __argv) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
int  execve(const char * __file, char * const * __argv, char * const * __envp) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
int  execvp(const char * __file, char * const * __argv) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;

原文:https://www.cnblogs.com/iamfatotaku/p/12516468.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!