当前位置: 首页> 文旅> 文化 > 怎么做网页 在浏览器上_吉林网站建设费用_营销对企业的重要性_宁波网站建设推广公司价格

怎么做网页 在浏览器上_吉林网站建设费用_营销对企业的重要性_宁波网站建设推广公司价格

时间:2025/7/9 16:19:14来源:https://blog.csdn.net/qq_43441284/article/details/146215981 浏览次数:0次
怎么做网页 在浏览器上_吉林网站建设费用_营销对企业的重要性_宁波网站建设推广公司价格

什么是进程

进程是程序的一次执行过程,是操作系统进行资源分配和调度的基本单位。它包含了程序执行的上下文环境,如代码、数据、打开的文件描述符、信号处理函数等。每个进程在操作系统中都有唯一的标识符(PID,Process ID),操作系统通过 PID 来管理和控制进程。

进程控制块PCB(Process Control Block)

PCB 是进程存在的唯一标志,当操作系统创建一个新进程时,会为其分配一个 PCB;当进程终止时,操作系统会回收其 PCB。每个进程都有一个与之对应的 PCB,操作系统通过对 PCB 的操作来实现对进程的控制和管理。

作用

进程标识:每个 PCB 都有一个唯一的标识符,即进程 ID(PID),用于区分不同的进程。
进程控制:操作系统通过 PCB 来控制进程的执行,如进程的创建、暂停、继续、终止等操作。
进程调度:调度程序根据 PCB 中的信息(如优先级、状态等)来决定哪个进程可以获得 CPU 资源,以及何时获得 CPU 资源。
资源管理:PCB 记录了进程所占用的各种资源,如内存、文件、设备等,操作系统可以根据这些信息进行资源的分配和回收。
上下文切换:当进程被暂停执行时,其当前的执行上下文(如寄存器值、程序计数器等)会被保存到 PCB 中;当进程再次获得 CPU 资源时,操作系统会从 PCB 中恢复其执行上下文,使进程能够继续执行。
包含信息
不同操作系统的 PCB 所包含的信息可能会有所不同,但一般都包含以下几类信息:

进程标识符

内部标识符:操作系统为每个进程分配的唯一数字标识符,用于在操作系统内部对进程进行管理和识别。
外部标识符:由用户或应用程序使用的标识符,通常是一个字符串,用于方便用户或应用程序对进程进行操作和管理。
处理机状态
通用寄存器:用于保存进程在执行过程中的中间结果和临时数据。
程序计数器(PC):指示下一条要执行的指令的地址。
状态寄存器:保存进程的运行状态信息,如进位标志、溢出标志等。
栈指针:指向进程栈的栈顶地址,用于管理进程的函数调用和局部变量。

进程调度信息

进程状态:如就绪、运行、阻塞、终止等,用于描述进程当前的执行状态。
优先级:用于确定进程在调度时的优先顺序,优先级高的进程通常会优先获得 CPU 资源。
调度相关信息:如进程的等待时间、执行时间等,用于调度算法的计算和决策。

进程控制信息

程序和数据的地址:指示进程的程序代码和数据在内存中的存储位置。
进程同步和通信机制:如信号量、消息队列等,用于实现进程之间的同步和通信。
资源清单:记录进程所占用的各种资源,如内存、文件、设备等。
链接指针:用于将多个 PCB 组织成某种数据结构,如链表、队列等。

进程ID

getpid():返回当前进程的进程 ID(PID)。
getppid():返回当前进程的父进程 ID(PPID)。
getuid():返回当前进程的实际用户 ID(UID)。
geteuid():返回当前进程的有效用户 ID(EUID)。
getgid():返回当前进程的实际组 ID(GID)。
getegid():返回当前进程的有效组 ID(EGID)

#include <iostream>
#include <unistd.h>  // 包含系统调用函数的头文件int main() {// 获取当前进程的进程IDpid_t pid = getpid();std::cout << "当前进程的进程ID (PID): " << pid << std::endl;// 获取当前进程的父进程IDpid_t ppid = getppid();std::cout << "当前进程的父进程ID (PPID): " << ppid << std::endl;// 获取当前进程的实际用户IDuid_t uid = getuid();std::cout << "当前进程的实际用户ID (UID): " << uid << std::endl;// 获取当前进程的有效用户IDuid_t euid = geteuid();std::cout << "当前进程的有效用户ID (EUID): " << euid << std::endl;// 获取当前进程的实际组IDgid_t gid = getgid();std::cout << "当前进程的实际组ID (GID): " << gid << std::endl;// 获取当前进程的有效组IDgid_t egid = getegid();std::cout << "当前进程的有效组ID (EGID): " << egid << std::endl;return 0;
}

在这里插入图片描述

多进程调度原理

操作系统采用多种调度算法来决定在多个进程之间如何分配 CPU 时间。常见的调度算法有先来先服务(FCFS)、短作业优先(SJF)、优先级调度、时间片轮转调度等。这些算法根据进程的特性(如预计执行时间、优先级等)和系统资源的使用情况,合理地安排进程的执行顺序,以提高系统的整体性能和资源利用率。

先来先服务(FCFS)调度算法

原理:按照进程进入就绪队列的先后顺序来分配 CPU。先进入队列的进程先获得 CPU 资源,一直执行到完成或因某种原因阻塞才释放 CPU。
优点:实现简单,公平性好,每个进程都按照其到达的先后顺序获得服务,不会出现进程被饿死的情况。
缺点:如果有一个长作业先进入队列,那么后面的短作业即使已经就绪,也必须等待长作业执行完成才能得到处理,导致短作业的平均等待时间可能很长,系统的整体效率不高。

短作业优先(SJF)调度算法

原理:从就绪队列中选择预计执行时间最短的进程来分配 CPU。这种算法假设每个进程的执行时间是已知的,它总是优先选择执行时间短的作业,以减少平均周转时间。
优点:可以有效地降低作业的平均等待时间,提高系统的吞吐量。因为短作业能够更快地完成,释放资源,让其他作业有更多机会使用 CPU。
缺点:需要事先知道每个作业的执行时间,这在实际中往往是难以准确预测的。而且该算法可能导致长作业长时间等待,甚至出现饥饿现象,即长作业可能一直得不到执行的机会。

优先级调度算法

原理:为每个进程分配一个优先级,根据优先级的高低来决定进程的执行顺序。优先级高的进程优先获得 CPU 资源,当有更高优先级的进程进入就绪队列时,当前正在执行的低优先级进程可能会被抢占,除非系统采用非抢占式优先级调度,即只有当高优先级进程主动放弃 CPU 或阻塞时,低优先级进程才有机会执行。
优点:可以根据进程的重要性或紧急程度来分配 CPU 资源,确保关键任务能够优先得到处理。
缺点:如果不采取适当的措施,低优先级的进程可能会长期处于等待状态,出现饥饿现象。此外,如何合理地确定进程的优先级也是一个复杂的问题,需要综合考虑多种因素。

时间片轮转调度算法

原理:将 CPU 的时间划分成一个个固定长度的时间片,每个进程轮流在一个时间片内执行。当时间片用完后,无论进程是否执行完成,都将被暂停,然后将 CPU 分配给下一个就绪进程。如此循环,直到所有进程都执行完毕或满足某种结束条件。
优点:可以保证每个进程都能在一定时间内获得 CPU 资源,实现了进程之间的公平调度,用户会感觉系统在同时处理多个任务,提高了系统的响应速度和交互性。
缺点:由于进程的切换需要保存和恢复现场等操作,会带来一定的系统开销。如果时间片设置得太短,会导致进程切换过于频繁,系统开销增大;如果时间片设置得太长,又会退化为类似 FCFS 算法,无法及时响应其他进程的请求。

fork创建子进程

fork函数是 UNIX/Linux 系统中用于创建子进程的系统调用。调用fork函数后,操作系统会为新的子进程分配资源,包括内存空间、文件描述符等,并复制父进程的上下文环境。子进程几乎是父进程的一个副本,它们从fork函数调用点开始并发执行不同的代码分支,通过fork函数的返回值来区分父子进程,父进程返回子进程的 PID,子进程返回 0。

#include <iostream>
#include <unistd.h>  // 包含fork()函数的头文件int main() {// 调用fork()函数创建子进程pid_t pid = fork();// 检查fork()的返回值if (pid < 0) {// fork()失败,输出错误信息std::cerr << "Fork failed!" << std::endl;return 1;} else if (pid == 0) {// 子进程,fork()返回值为0std::cout << "This is the child process. Its PID is: " << getpid() << std::endl;std::cout << "The parent PID of the child process is: " << getppid() << std::endl;} else {// 父进程,fork()返回子进程的PIDstd::cout << "This is the parent process. Its PID is: " << getpid() << std::endl;std::cout << "The PID of the child process is: " << pid << std::endl;}return 0;
}

包含头文件:
#include :用于输入输出操作。
#include <unistd.h>:包含了fork()函数以及getpid()和getppid()函数的声明。getpid()用于获取当前进程的 PID,getppid()用于获取当前进程的父进程的 PID。
调用fork()函数:
pid_t pid = fork();:调用fork()函数创建子进程。fork()函数会返回两次,在父进程中返回子进程的 PID,在子进程中返回 0,如果创建失败则返回 - 1。
检查fork()的返回值:
if (pid < 0):表示fork()调用失败,输出错误信息并返回 1。
else if (pid == 0):表示当前代码在子进程中执行,输出子进程的 PID 和父进程的 PID。
else:表示当前代码在父进程中执行,输出父进程的 PID 和子进程的 PID。
在这里插入图片描述

什么是子进程

子进程是由另一个进程(父进程)通过fork或其他类似机制创建的新进程。子进程继承了父进程的许多属性,如用户 ID、组 ID、环境变量、文件描述符等,但它有自己独立的 PID 和内存空间,与父进程并发执行,在一定程度上可以看作是一个独立的程序在运行。

子进程和父进程的关系

父子关系:父进程创建子进程,它们之间存在明确的父子层次结构。​
资源继承:子进程继承父进程的部分资源,如打开的文件描述符,这意味着父进程打开的文件在子进程中仍然保持打开状态。​
并发执行:父子进程并发运行,它们的执行顺序由操作系统的调度算法决定。​
生命周期关联:一般情况下,父进程可以通过wait系列函数等待子进程结束,并获取子进程的退出状态,子进程的结束也可能会影响父进程的后续行为。

父子进程对文件的操作

由于子进程继承了父进程的文件描述符,父子进程对同一文件描述符所指向的文件进行操作时,具有一些特殊的行为。例如,父子进程共享文件的偏移量,一个进程对文件的写入操作会影响另一个进程对文件的读取位置。但如果在fork之后,某个进程又单独打开了同一个文件,那么它会得到一个新的文件描述符,与父进程的文件描述符相互独立,对文件的操作也相互独立。

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>#define BUFFER_SIZE 100
#define FILE_NAME "test_file.txt"int main() {pid_t pid = fork();if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;} else if (pid == 0) {// 子进程sleep(1); // 等待父进程完成写入操作FILE *fp = fopen(FILE_NAME, "r");if (fp == nullptr) {std::cerr << "Child process: Failed to open file!" << std::endl;return 1;}char buffer[BUFFER_SIZE];memset(buffer, 0, BUFFER_SIZE);size_t bytesRead = fread(buffer, sizeof(char), BUFFER_SIZE - 1, fp);if (bytesRead > 0) {std::cout << "Child process: Read from file: " << buffer << std::endl;}fclose(fp);} else {// 父进程FILE *fp = fopen(FILE_NAME, "w");if (fp == nullptr) {std::cerr << "Parent process: Failed to open file!" << std::endl;return 1;}const char *message = "Hello, this is written by the parent process!";fwrite(message, sizeof(char), strlen(message), fp);fclose(fp);std::cout << "Parent process: Wrote to file." << std::endl;// 等待子进程结束int status;waitpid(pid, &status, 0);}return 0;
}

头文件包含:
:用于标准输入输出操作。
<unistd.h>:包含 fork() 和 sleep() 等函数。
<fcntl.h>:提供文件控制相关的函数和常量。
:用于字符串操作,如 strlen 和 memset。
<sys/types.h> 和 <sys/wait.h>:提供进程相关的类型和 waitpid 函数。
常量定义:
BUFFER_SIZE:定义读取文件时使用的缓冲区大小。
FILE_NAME:指定要操作的文件名称。
fork() 函数调用:
通过 fork() 创建子进程,依据返回值判断当前是父进程还是子进程。
子进程操作:
调用 sleep(1) 让子进程等待 1 秒,确保父进程完成文件写入操作。
以只读模式打开文件,若打开失败则输出错误信息。
使用 fread 函数从文件读取数据到缓冲区,并输出读取到的内容。
关闭文件。
父进程操作:
以写入模式打开文件,若打开失败则输出错误信息。
使用 fwrite 函数将字符串写入文件。
关闭文件并输出写入成功的信息。
调用 waitpid 等待子进程结束。
在这里插入图片描述

关键字:怎么做网页 在浏览器上_吉林网站建设费用_营销对企业的重要性_宁波网站建设推广公司价格

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: