实验二:多进程 并发执行
计算机操作系统实验二
计算机操作系统实验二一、实验目的本实验旨在通过实际操作,深入理解和掌握计算机操作系统中的进程与线程管理。
通过实验,我们将了解进程的创建、执行、阻塞、唤醒等状态以及线程的创建、同步、通信等操作。
同时,通过实验,我们将学习如何利用进程和线程提高程序的并发性和效率。
二、实验内容1、进程管理a.进程的创建与执行:通过编程语言(如C/C++)编写一个程序,创建一个新的进程并执行。
观察和记录进程的创建、执行过程。
b.进程的阻塞与唤醒:编写一个程序,使一个进程在执行过程中发生阻塞,并观察和记录阻塞状态。
然后,通过其他进程唤醒该进程,并观察和记录唤醒过程。
c.进程的状态转换:根据实际操作,理解和分析进程的状态转换(就绪状态、阻塞状态、执行状态)以及转换的条件和过程。
2、线程管理a.线程的创建与同步:编写一个多线程程序,创建多个线程并观察和记录线程的创建过程。
同时,使用同步机制(如互斥锁或信号量)实现线程间的同步操作。
b.线程的通信:通过消息队列或其他通信机制,实现多个线程间的通信。
观察和记录线程间的通信过程以及通信对程序执行的影响。
c.线程的状态转换:根据实际操作,理解和分析线程的状态转换(新建状态、就绪状态、阻塞状态、终止状态)以及转换的条件和过程。
三、实验步骤1、按照实验内容的要求,编写相应的程序代码。
2、编译并运行程序,观察程序的执行过程。
3、根据程序的输出和实际操作情况,分析和理解进程与线程的状态转换以及进程与线程管理的相关原理。
4、修改程序代码,尝试不同的操作方式,观察程序执行结果的变化,进一步深入理解和掌握进程与线程管理。
5、完成实验报告,总结实验过程和结果,提出问题和建议。
四、实验总结通过本次实验,我们深入了解了计算机操作系统中的进程与线程管理原理和实践操作。
在实验过程中,我们不仅学习了如何利用编程语言实现进程和线程的操作,还通过实际操作观察和分析了进程与线程的状态转换以及进程与线程管理的基本原理。
操作系统实验二并发与调度
实验二并发与调度一、实验目的在本实验中,通过对事件和互斥体对象的了解,来加深对Windows 2000线程同步的理解。
通过分析实验程序,了解管理事件对象的API。
了解在进程中如何使用事件对象,在进程中如何使用互斥体对象,线程如何通过文件映射对象发送数据。
二、实验环境硬件环境:计算机一台,局域网环境;软件环境:Windows 2000 Professional,Visual C++ 6.0专业版或企业版。
三、实验内容和步骤第一部分:互斥体对象本程序中显示的类CCountUpDown使用了一个互斥体来保证对两个线程间单一数值的访问。
每个线程都企图获得控制权来改变该数值,然后将该数值写入输出流中。
创建者实际上创建的是互斥体对象,计数方法执行等待并释放,为的是共同使用互斥体所需的资源(因而也就是共享资源) 。
1、利用互斥体保护共享资源程序参见实验指导书分析程序的运行结果,可以看到线程(加和减线程) 的交替执行(因为Sleep() API允许Windows切换线程) 。
在每次运行之后,数值应该返回初始值(0) ,因为在每次运行之后写入线程在等待队列中变成最后一个,内核保证它在其他线程工作时不会再运行。
1)请描述运行结果(如果运行不成功,则可能的原因是什么?) :2) 根据运行输出结果,对照分析程序,可以看出程序运行的流程吗?请简单描述:_____逆向运行__________第二部分线程通过文件对象发送数据Windows 2000提供的线程间通讯类内核对象允许同一进程或跨进程的线程之间互相发送信息,包括文件、文件映射、邮件位和命名管道等,其中最常用的是文件和文件映射。
这类对象允许一个线程很容易地向同一进程或其他进程中的另一线程发送信息。
1、演示线程通过文件对象发送数据程序参见实验指导书运行结果(如果运行不成功,则可能的原因是什么?) :阅读和分析程序,请回答问题:1) 程序中启动了多少个单独的读写线程?__________100__________________________________________________________2) 使用了哪个系统API函数来创建线程例程?_________ CreateThread()________________________________3) 文件的读和写操作分别使用了哪个API函数?_______ ReadFile()______ WriteFile()_____________ 每次运行进程时,都可看到程序中的每个线程从前面的线程中读取数据并将数据增加,文件中的数值连续增加。
操作系统实验报告模板
操作系统实验报告模板一、实验目的本次操作系统实验的主要目的是通过实际操作和观察,深入理解操作系统的核心概念和功能,包括进程管理、内存管理、文件系统、设备管理等方面。
同时,培养学生的动手能力、问题解决能力和团队合作精神,提高对操作系统原理的掌握程度和实际应用能力。
二、实验环境1、操作系统:_____(具体操作系统名称及版本)2、开发工具:_____(如编译器、调试器等)3、硬件环境:_____(处理器型号、内存大小等)三、实验内容(一)进程管理实验1、进程创建与终止使用系统调用创建多个进程,并观察进程的创建过程和资源分配情况。
实现进程的正常终止和异常终止,观察终止时的系统行为。
2、进程调度研究不同的进程调度算法,如先来先服务(FCFS)、短作业优先(SJF)、时间片轮转(RR)等。
通过编程模拟实现这些调度算法,并比较它们的性能。
3、进程同步与互斥利用信号量、互斥锁等机制实现进程之间的同步与互斥。
编写多进程程序,模拟生产者消费者问题、读者写者问题等经典同步场景。
(二)内存管理实验1、内存分配与回收实现不同的内存分配算法,如首次适应算法、最佳适应算法、最坏适应算法等。
观察内存分配和回收的过程,分析算法的优缺点。
2、虚拟内存了解虚拟内存的概念和实现原理。
通过设置页表、进行页面置换等操作,模拟虚拟内存的管理过程。
(三)文件系统实验1、文件操作实现文件的创建、打开、读写、关闭等基本操作。
研究文件的属性(如权限、大小、创建时间等)的设置和获取。
2、目录管理创建、删除目录,遍历目录结构。
实现文件和目录的重命名、移动等操作。
(四)设备管理实验1、设备驱动程序了解设备驱动程序的结构和工作原理。
编写简单的设备驱动程序,实现对特定设备的控制和数据传输。
2、设备分配与回收研究设备分配的策略,如独占式分配、共享式分配等。
实现设备的分配和回收过程,观察系统的资源利用情况。
四、实验步骤(一)进程管理实验步骤1、进程创建与终止编写程序,使用系统调用创建指定数量的进程。
程序并发执行实验报告
一、实验目的1. 理解并发执行的概念和原理。
2. 掌握多线程编程的基本方法。
3. 学会使用同步机制解决并发编程中的竞争条件。
4. 分析并发程序的性能和效率。
二、实验环境1. 操作系统:Windows 102. 编程语言:Java3. 开发工具:Eclipse三、实验内容1. 创建一个简单的并发程序,实现两个线程同时执行。
2. 使用同步机制解决并发程序中的竞争条件。
3. 分析并发程序的性能和效率。
四、实验步骤1. 创建一个简单的并发程序(1)创建一个名为ConcurrentTest的类,该类继承自Thread类。
(2)在ConcurrentTest类的run方法中,打印出当前线程的名字。
(3)在主函数中,创建两个ConcurrentTest对象,分别命名为thread1和thread2。
(4)启动thread1和thread2线程。
(5)等待thread1和thread2线程执行完毕。
2. 使用同步机制解决并发程序中的竞争条件(1)创建一个名为Counter的类,该类包含一个私有变量count和一个静态同步方法add。
(2)在add方法中,增加count变量的值。
(3)在主函数中,创建一个Counter对象counter。
(4)创建两个线程,分别调用counter对象的add方法。
(5)启动两个线程,并等待它们执行完毕。
3. 分析并发程序的性能和效率(1)在主函数中,记录两个线程开始执行的时间。
(2)在主函数中,记录两个线程执行完毕的时间。
(3)计算两个线程执行所需的时间差。
五、实验结果与分析1. 实验结果(1)简单的并发程序在控制台中,可以看到thread1和thread2线程交替打印出它们的名字。
(2)使用同步机制解决竞争条件在控制台中,可以看到Counter对象的count变量值正确地增加了。
(3)分析并发程序的性能和效率thread1和thread2线程执行所需的时间差为0.01秒。
2. 实验分析(1)简单的并发程序通过创建两个线程,实现了两个任务同时执行。
操作系统实验fork()
并发程序设计【实验目的】:掌握在程序中创建新进程的方法,观察并理解多道程序并发执行的现象。
【实验原理】:fork():建立子进程。
子进程得到父进程地址空间的一个复制。
返回值:成功时,该函数被调用一次,但返回两次,fork()对子进程返回0,对父进程返回子进程标识符(非0值)。
不成功时对父进程返回-1,没有子进程。
【实验内容】:首先分析一下程序运行时其输出结果有哪几种可能性,然后实际调试该程序观察其实际输出情况,比较两者的差异,分析其中的原因。
void main (void){ int x=5;if( fork(()){x+=30;printf (“%d\n”,x);}elseprintf(“%d\n”,x);printf((“%d\n”,x);}【实验要求】:每个同学必须独立完成本实验、提交实验报告、源程序和可执行程序。
实验报告中必须包含预计的实验结果,关键代码的分析,调试记录,实际的实验结果,实验结果分析等内容。
一.源程序1.1程序.#include<stdio.h>#include<sys/types.h>//pid_t类型的定义#include<unistd.h>//函数fork().getpid()定义void main (void){int x=5;if( fork( ) ){x+=30;printf ("%d\n",x);}elseprintf("%d\n",x);printf("%d\n",x);}1.2预测结果:(1)553535(2)353555(3)535535(4)535355(5)355355(6)355535(7)35351.3实际结果:administrator@ubuntu:~/yanhong$ cc 1.cadministrator@ubuntu:~/yanhong$ ./a.out353555administrator@ubuntu:~/yanhong$ cc 1.cadministrator@ubuntu:~/yanhong$ ./a.out5535351.4结果分析:结果表明,子进程先执行还是父进程先执行是不确定的。
实验二 进程管理(linux)
实验二进程管理(Linux)一、实验类型本实验为设计性实验。
二、实验目的与任务1)加深对进程概念的理解,明确进程和程序的区别。
2)进一步认识并发执行的实质三、预习要求1)进程的概念2)进程控制的概念及内容3)进程的并发执行4)熟悉互斥的概念5)用到的Linux函数有:fork(),lockf()等。
四、实验基本原理使用fork()系统调用来创建一个子进程,父进程和子进程并发执行,交替输出结果。
使用lockf()系统调用对临界区进行加锁操作,实现对共享资源的互斥使用。
五、实验仪器与设备(或工具软件)实验设备:计算机一台,软件环境要求: Linux操作系统和gcc编译器。
六、实验内容1)进程的创建编写一段程序,使用系统调用fork( ) 创建两个子程序。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。
运行程序10次,观察记录屏幕上的显示结果,并分析原因。
2)进程的控制修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。
如果在程序中使用系统调用lockf()来给每一个进程加锁,可以实现进程间的互斥,观察并分析出现的现象。
(1)进程的创建参考程序如下:#include<stdio.h>main(){int p1,p2;while((p1=fork())==-1); //p父进程p1子进程1if(p1!=0){while(((p2=fork())==-1); //p父进程p2子进程2if(p2==0) putchar('b');else putchar('c');}else putchar('a');}运行结果:略cab bca bac分析:原因:Fork()函数有三个返回值:1.-1 执行不成功2.0 表示当前正在执行子进程3.其他数值表示当前正在执行父进程,值是子进程的进程标识符PID4.获取当前进程的标识符getpid()5.获取当前进程的父进程的标识符getppid()(2)进程的控制参考程序如下#include<stdio.h>main(){int p1,p2,i;while ((p1=fork())==-1); // 父进程p,子进程p1if(p1==0){for(i=0;i<500;i++)printf("child_p1_ %d\n",i);}else{while((p2=fork())==-1);//父进程p,子进程p2if(p2==0)for(i=0;i<500;i++)printf("chind_p2_ %d\n",i);else for(i=0;i<500;i++)printf("father_p_%d\n",i);}}运行结果:略分析:由于函数printf()输出和字符串之间不会被中断,因此字符串内部的字符顺序输出不变。
进程管理实验报告分析(3篇)
第1篇一、实验背景进程管理是操作系统中的一个重要组成部分,它负责管理计算机系统中所有进程的创建、调度、同步、通信和终止等操作。
为了加深对进程管理的理解,我们进行了一系列实验,以下是对实验的分析和总结。
二、实验目的1. 加深对进程概念的理解,明确进程和程序的区别。
2. 进一步认识并发执行的实质。
3. 分析进程争用资源的现象,学习解决进程互斥的方法。
4. 了解Linux系统中进程通信的基本原理。
三、实验内容1. 使用系统调用fork()创建两个子进程,父进程和子进程分别显示不同的字符。
2. 修改程序,使每个进程循环显示一句话。
3. 使用signal()捕捉键盘中断信号,并通过kill()向子进程发送信号,实现进程的终止。
4. 分析利用软中断通信实现进程同步的机理。
四、实验结果与分析1. 实验一:父进程和子进程分别显示不同的字符在实验一中,我们使用fork()创建了一个父进程和两个子进程。
在父进程中,我们打印了字符'a',而在两个子进程中,我们分别打印了字符'b'和字符'c'。
实验结果显示,父进程和子进程的打印顺序是不确定的,这是因为进程的并发执行。
2. 实验二:每个进程循环显示一句话在实验二中,我们修改了程序,使每个进程循环显示一句话。
实验结果显示,父进程和子进程的打印顺序仍然是随机的。
这是因为并发执行的进程可能会同时占用CPU,导致打印顺序的不确定性。
3. 实验三:使用signal()捕捉键盘中断信号,并通过kill()向子进程发送信号在实验三中,我们使用signal()捕捉键盘中断信号(按c键),然后通过kill()向两个子进程发送信号,实现进程的终止。
实验结果显示,当按下c键时,两个子进程被终止,而父进程继续执行。
这表明signal()和kill()在进程控制方面具有重要作用。
4. 实验四:分析利用软中断通信实现进程同步的机理在实验四中,我们分析了利用软中断通信实现进程同步的机理。
进程的调度实验报告(3篇)
第1篇一、实验目的通过本次实验,加深对操作系统进程调度原理的理解,掌握先来先服务(FCFS)、时间片轮转(RR)和动态优先级(DP)三种常见调度算法的实现,并能够分析这些算法的优缺点,提高程序设计能力。
二、实验环境- 编程语言:C语言- 操作系统:Linux- 编译器:GCC三、实验内容本实验主要实现以下内容:1. 定义进程控制块(PCB)结构体,包含进程名、到达时间、服务时间、优先级、状态等信息。
2. 实现三种调度算法:FCFS、RR和DP。
3. 创建一个进程队列,用于存储所有进程。
4. 实现调度函数,根据所选算法选择下一个执行的进程。
5. 模拟进程执行过程,打印进程执行状态和就绪队列。
四、实验步骤1. 定义PCB结构体:```ctypedef struct PCB {char processName[10];int arrivalTime;int serviceTime;int priority;int usedTime;int state; // 0: 等待,1: 运行,2: 完成} PCB;```2. 创建进程队列:```cPCB processes[MAX_PROCESSES]; // 假设最多有MAX_PROCESSES个进程int processCount = 0; // 实际进程数量```3. 实现三种调度算法:(1)FCFS调度算法:```cvoid fcfsScheduling() {int i, j;for (i = 0; i < processCount; i++) {processes[i].state = 1; // 设置为运行状态printf("正在运行进程:%s\n", processes[i].processName); processes[i].usedTime++;if (processes[i].usedTime == processes[i].serviceTime) { processes[i].state = 2; // 设置为完成状态printf("进程:%s 完成\n", processes[i].processName); }for (j = i + 1; j < processCount; j++) {processes[j].arrivalTime--;}}}```(2)RR调度算法:```cvoid rrScheduling() {int i, j, quantum = 1; // 时间片for (i = 0; i < processCount; i++) {processes[i].state = 1; // 设置为运行状态printf("正在运行进程:%s\n", processes[i].processName); processes[i].usedTime++;processes[i].serviceTime--;if (processes[i].serviceTime <= 0) {processes[i].state = 2; // 设置为完成状态printf("进程:%s 完成\n", processes[i].processName); } else {processes[i].arrivalTime++;}for (j = i + 1; j < processCount; j++) {processes[j].arrivalTime--;}}}```(3)DP调度算法:```cvoid dpScheduling() {int i, j, minPriority = MAX_PRIORITY;int minIndex = -1;for (i = 0; i < processCount; i++) {if (processes[i].arrivalTime <= 0 && processes[i].priority < minPriority) {minPriority = processes[i].priority;minIndex = i;}}if (minIndex != -1) {processes[minIndex].state = 1; // 设置为运行状态printf("正在运行进程:%s\n", processes[minIndex].processName);processes[minIndex].usedTime++;processes[minIndex].priority--;processes[minIndex].serviceTime--;if (processes[minIndex].serviceTime <= 0) {processes[minIndex].state = 2; // 设置为完成状态printf("进程:%s 完成\n", processes[minIndex].processName); }}}```4. 模拟进程执行过程:```cvoid simulateProcess() {printf("请选择调度算法(1:FCFS,2:RR,3:DP):");int choice;scanf("%d", &choice);switch (choice) {case 1:fcfsScheduling();break;case 2:rrScheduling();break;case 3:dpScheduling();break;default:printf("无效的调度算法选择。
操作系统实验-进程控制
实验一、进程控制实验1.1 实验目的加深对于进程并发执行概念的理解。
实践并发进程的创建和控制方法。
观察和体验进程的动态特性。
进一步理解进程生命期期间创建、变换、撤销状态变换的过程。
掌握进程控制的方法,了解父子进程间的控制和协作关系。
练习 Linux 系统中进程创建与控制有关的系统调用的编程和调试技术。
1.2 实验说明1)与进程创建、执行有关的系统调用说明 进程可以通过系统调用fork()创建子进程并和其子进程并发执行.子进程初始的执行映像是父进程的一个复本.子进程可以通过 exec()系统调用族装入一个新的执行程序。
父进程可以使用 wait()或 waitpid()系统调用等待子进程的结束并负责收集和清理子进程的退出状态。
fork()系统调用语法:pid_t#include <unistd.h>fork(void);fork 成功创建子进程后将返回子进程的进程号,不成功会返回-1.exec 系统调用有一组 6 个函数,其中示例实验中引用了 execve 系统调用语法:#include <unistd.h>const char * envp[]);path 要装const char *argv[],int execve(const char *path,入的新的执行文件的绝对路径名字符串.argv[] 要传递给新执行程序的完整的命令参数列表(可以为空).envp[] 要传递给新执行程序的完整的环境变量参数列表(可以为空).Exec 执行成功后将用一个新的程序代替原进程,但进程号不变,它绝不会再返回到调用进程了。
如果 exec 调用失败,它会返回-1。
wait() 系统调用语法:#include <sys/types.h>pid_t#include <sys/wait.h>wait(int *status);status 用pid_t waitpid(pid_t pid,int *status,int option);于保留子进程的退出状态pid 可以为以下可能值:-1 等待所有 PGID 等于 PID 的绝对值的子进程1 等待所有子进程0 等待所有 PGID 等于调用进程的子进程>0 等待 PID 等于 pid 的子进程 option 规定了调用 waitpid 进程的行为:WNOHANG 没有子进程时立即返回WUNTRACED 没有报告状态的进程时返回wait 和 waitpid 执行成功将返回终止的子进程的进程号,不成功返回-1。
实验报告模板2
写入磁盘的运行时间:
写入磁盘的 test.ini 的截图
计算 800000000 次数据的时间:
串行时间
并行时间:
实验结论:由上图可知,基本实现了实验要求。由图可以得到,写入磁盘时间与计算时 间都已经调整为 5s 左右,在上图中由于每次运行程序时系统误差,因此会导致每一次 运行写文件以及计算的时间都不同,但很明显,串行计算得到的时间在误差范围内等于 两个子文件单独运行的时间之和。并行计算的时间在误差范围内基本上与两者独立计算 的时间相同。
第一个为对象句柄(pisz.hProcess),第二个为等待最长时间(以毫秒计,也 可以为 INFINITE) 。 本实验中,可以采用以下方式调用: WaitForInputIdle(pisz.hProcess,INFINITE);; 3 核心源代码 (1)计算数据,并同时向 U 盘写入数据 void WriteOrCalculate() { STARTUPINFO sui;//用于指定新进程的主窗口特性 PROCESS_INFORMATION piszWriteFile,piszCalculate; BOOL wProcess,cProcess; //设置创建进程信息 memset(&sui,0,sizeof(STARTUPINFO));//将 s 中后 n 个字节 用 0 替换并返回 s 。 sui.cb =sizeof(STARTUPINFO);//CB 包含 STARTUPINFO 结构中的字节数,初始化操 作
cProcess = CreateProcess(szCalculate,NULL,NULL,NULL,TRUE,0,NULL, NULL,&sui,&piszCalculate); wProcess =CreateProcess(szWriteFile,NULL,NULL,NULL,TRUE,0,NULL, NULL,&sui,&piszWriteFile); WaitForInputIdle(piszWriteFile.hProcess,INFINITE); //等待新进程完成它的 初始化并等待用户输入。 WaitForInputIdle(piszCalculate.hProcess,INFINITE); } (2)先计算数据,然后向 U 盘写入数据 void WriteAndCalculate() { //启动执行文件 WinExec(szCalculate,NULL); WinExec(szWriteFile,NULL); } (3)开始计时 DWORD StartTime,StopTime; void StartTimeCount(HWND hWnd,LPSTR StartString) { HDC hDC; hDC =GetDC(hWnd); TextOut(hDC,100,100,StartString,strlen(StartString)); //设备环境的句柄,用于字符串对齐的基准点的逻辑 X 坐标,逻辑 Y 坐标,将被绘制
进程并发实验报告
一、实验背景与目的随着计算机技术的发展,多任务处理和多进程并发已经成为操作系统设计中的基本要求。
为了更好地理解进程并发的基本原理和实现方法,我们进行了本次实验。
实验的目的是通过实践操作,加深对进程并发执行的理解,掌握进程创建、同步、互斥等基本概念,并学会使用相关系统调用实现进程的并发控制。
二、实验环境与工具实验环境:Windows 10操作系统,Visual Studio 2019开发环境。
实验工具:C++编程语言,WinAPI系统调用。
三、实验内容与步骤本次实验主要分为以下几个部分:1. 进程创建与并发执行- 使用CreateProcess函数创建多个进程,并观察它们的并发执行情况。
- 使用GetTickCount函数获取每个进程的执行时间,分析并发执行的效果。
2. 进程同步- 使用互斥锁(mutex)实现进程间的同步,确保同一时刻只有一个进程访问共享资源。
- 使用条件变量(condition variable)实现进程间的条件同步,实现生产者-消费者模型。
3. 进程互斥- 使用信号量(semaphore)实现进程间的互斥,避免资源竞争。
- 使用临界区(critical section)保护共享资源,防止多个进程同时访问。
4. 实验分析- 分析实验结果,总结进程并发、同步和互斥的原理和方法。
- 讨论实验中遇到的问题和解决方法。
四、实验代码示例以下是一个简单的实验代码示例,演示了使用互斥锁实现进程同步的过程:```cpp#include <windows.h>#include <iostream>using namespace std;// 全局互斥锁mutex mtx;void processFunction(){unique_lock<mutex> lock(mtx);cout << "Process " << GetCurrentProcessId() << " is running." << endl;lock.unlock();}int main(){// 创建两个进程CreateProcess(NULL, "process.exe", NULL, NULL, FALSE, 0, NULL, NULL, NULL, NULL);// 主进程继续执行cout << "Main process is running." << endl;return 0;}```五、实验结果与分析1. 进程创建与并发执行通过实验,我们观察到多个进程可以并发执行,并且每个进程的执行时间都会有所不同。
最新进程的创建与并发执行-带答案版
实验二进程管理2.1 进程的创建与并发执行1.实验目的(1) 加深对进程概念的理解,理解进程和程序的区别。
(2) 认识并发进程的实质。
分析进程争用资源的现象,学习解决进程互斥的方法。
(3) 理解系统调用和用户命令的区别。
2.实验类型:验证型3.实验学时:24.实验原理和知识点(1) 实验原理:程序的并发执行具有随机性和不可再现性。
程序并发执行会导致资源共享和资源竞争,各程序向前执行的速度会受资源共享的制约。
程序的动态执行过程用进程这个概念来描述。
由于向前推进的速度不可预知,所以多个进程并发地重复执行,整体上得到的结果可能不同。
但要注意,就其中某单个进程而言,其多次运行结果是确定的。
(2) 知识点:进程、子进程、并发执行的特性;5.实验环境(硬件环境、软件环境):(1)硬件环境:Intel Pentium III 以上CPU,128MB以上内存,2GB以上硬盘(2)软件环境:linux操作系统。
6. 预备知识(1) fork()系统调用头文件:#include <unistd.h> unix standard header/*是POSIX标准定义的unix类系统定义符号常量的头文件,包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数*/函数原型: pid_t fork(void);/*是Linux下的进程号类型,也就是Process ID _ Type 的缩写。
其实是宏定义的unsigned int类型*/函数功能:fork的功能是创建子进程。
调用fork的进程称为父进程。
如图2.1所示。
子进程是父进程的一个拷贝,它继承了父进程的用户代码、组代码、环境变量、已打开的文件代码、工作目录及资源限制。
fork语句执行后,内核向父进程返回子进程的进程号,向子进程返回0。
父子进程都从fork()的下一句开始并发执行。
返回值:返回值==-1:创建失败。
返回值==0:程序在子进程中。
多线程并发实验报告
一、实验目的1. 理解多线程并发编程的基本概念和原理;2. 掌握Java多线程编程的基本方法和技巧;3. 学习线程同步机制,解决线程安全问题;4. 熟悉线程调度策略,提高程序性能。
二、实验环境1. 操作系统:Windows 102. 开发工具:IntelliJ IDEA3. JDK版本:1.8三、实验内容1. 线程创建与启动2. 线程同步与互斥3. 线程通信与协作4. 线程池与线程调度5. 线程局部变量与共享变量四、实验步骤及结果分析1. 线程创建与启动实验步骤:(1)创建一个继承自Thread类的子类;(2)重写run()方法,定义线程的执行逻辑;(3)创建Thread对象,并调用start()方法启动线程。
实验结果:成功创建并启动两个线程,分别执行各自的run()方法。
2. 线程同步与互斥实验步骤:(1)创建一个共享资源;(2)使用synchronized关键字声明同步方法或同步代码块;(3)在同步方法或同步代码块中访问共享资源。
实验结果:线程在访问共享资源时,能够保证互斥,防止数据不一致。
3. 线程通信与协作实验步骤:(1)使用wait()和notify()方法实现线程间的通信;(2)创建共享对象,作为线程间通信的媒介;(3)在等待线程中调用wait()方法,在通知线程中调用notify()方法。
实验结果:线程能够通过wait()和notify()方法实现通信与协作,完成特定任务。
4. 线程池与线程调度实验步骤:(1)使用Executors工厂方法创建线程池;(2)提交任务到线程池;(3)关闭线程池。
实验结果:线程池能够有效地管理线程,提高程序性能。
5. 线程局部变量与共享变量实验步骤:(1)创建线程局部变量;(2)创建共享变量;(3)在各个线程中访问和修改线程局部变量与共享变量。
实验结果:线程局部变量在各个线程中独立存在,不会相互干扰;共享变量在各个线程中共享,需要使用同步机制保证数据一致性。
实验二进程管理
实验二进程管理(一)实验目的或实验原理1.加深对进程概念的理解,明确进程和程序的区别。
2.进一步认识并发执行的实质。
3.分析进程竞争资源现象,学习解决进程互斥的方法。
4.了解Linux系统中进程通信的基本原理。
(二)实验内容1.进程的创建。
2.进程的控制。
3.①编写一段程序,使其现实进程的软中断通信。
要求:使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按DEL键);当捕捉到中断信号后,父进程用系统调用Kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:Child Processll is Killed by Parent!Child Processl2 is Killed by Parent!父进程等待两个子进程终止后,输出如下的信息后终止Parent Process is Killed!②在上面的程序中增加语句signal (SIGNAL, SIG-IGN) 和signal (SIGQUIT,SIG-IGN), 观察执行结果,并分析原因。
4.进程的管道通信。
编制一段程序,实现进程的管理通信。
使用系统调用pipe()建立一条管道线;两个子进程P1和P2分别向管道中写一句话:Child 1 is sending a message!Child 2 is sending a message!而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。
要求父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。
实验2 指导[实验内容]1.进程的创建〈任务〉编写一段程序,使用系统调用fork( )创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符;父进程显示字符“a”,子进程分别显示字符“b”和“c”。
试观察记录屏幕上的显示结果,并分析原因。
〈程序〉#include<stdio.h>main(){int p1,p2;if(p1=fork()) /*子进程创建成功*/putchar('b');else{if(p2=fork()) /*子进程创建成功*/putchar('c');else putchar('a'); /*父进程执行*/}}<运行结果>bca(有时会出现abc的任意的排列)分析:从进程执行并发来看,输出abc的排列都是有可能的。
进程管理操作系统linux实验
实验进程管理(一)进程的创建实验实验目的1、掌握进程的概念,明确进程的含义2、认识并了解并发执行的实质实验内容1、编写一段程序,使用系统调用fork()创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示'a',子进程分别显示字符'b'和字符'c'。
试观察记录屏幕上的显示结果,并分析原因。
2、修改上述程序,每一个进程循环显示一句话。
子进程显示'daughter…'及'son ……',父进程显示'parent ……',观察结果,分析原因。
实验准备(1)阅读LINUX的fork.c源码文件(见附录二),分析进程的创建过程。
(2)阅读LINUX的sched.c源码文件(见附录三),加深对进程管理概念的认识。
实验指导一、进程UNIX 中,进程既是一个独立拥有资源的基本单位,又是一个独立调度的基本单位。
一个进程实体由若干个区(段)组成,包括程序区、数据区、栈区、共享存储区等。
每个区又分为若干页,每个进程配置有唯一的进程控制块PCB,用于控制和管理进程。
PCB 的数据结构如下:1、进程表项(Process Table Entry)。
包括一些最常用的核心数据:进程标识符PID、用户标识符UID、进程状态、事件描述符、进程和U区在内存或外存的地址、软中断信号、计时域、进程的大小、偏置值nice、指向就绪队列中下一个PCB 的指针P_Link、指向U 区进程正文、数据及栈在内存区域的指针。
2、U 区(U Area)。
用于存放进程表项的一些扩充信息。
每一个进程都有一个私用的U区,其中含有:进程表项指针、真正用户标识符u-ruid(read user ID)、有效用户标识符u-euid(effective user ID)、用户文件描述符表、计时器、内部I/O参数、限制字段、差错字段、返回值、信号处理数组。
操作系统实验之进程管理实验报告
操作系统实验之进程管理实验报告一、实验目的本次操作系统实验的主要目的是深入理解进程管理的概念和原理,通过实际操作和观察,掌握进程的创建、调度、同步与互斥等关键机制。
二、实验环境本次实验使用的操作系统为 Windows 10,开发工具为 Visual Studio 2019,编程语言为 C++。
三、实验内容1、进程创建使用系统提供的 API 函数创建新的进程。
观察新进程的资源使用情况和运行状态。
2、进程调度编写程序模拟不同的进程调度算法,如先来先服务(FCFS)、短作业优先(SJF)和时间片轮转(RR)。
比较不同调度算法下的平均周转时间、平均等待时间等性能指标。
3、进程同步与互斥利用信号量、互斥锁等机制实现进程之间的同步与互斥。
设计并发程序,解决生产者消费者问题、读写者问题等经典同步问题。
四、实验步骤1、进程创建实验首先,包含所需的头文件,如`<windowsh>`。
然后,定义创建进程的函数,使用`CreateProcess` 函数创建新进程,并获取进程的相关信息,如进程标识符、线程标识符等。
最后,通过查看任务管理器或其他系统工具,观察新创建进程的资源占用情况。
2、进程调度实验设计不同的调度算法函数,如`FCFSSchedule`、`SJFSchedule` 和`RRSchedule`。
在每个调度算法函数中,模拟进程的到达时间、服务时间等参数,并按照相应的算法进行进程调度。
计算每个进程的周转时间和等待时间,并求出平均周转时间和平均等待时间。
3、进程同步与互斥实验定义信号量或互斥锁变量。
在生产者消费者问题中,生产者在生产产品时获取互斥锁,生产完成后释放互斥锁并通知消费者;消费者在消费产品时获取互斥锁,消费完成后释放互斥锁。
在读写者问题中,读者在读取数据时获取共享锁,读完后释放共享锁;写者在写入数据时获取独占锁,写入完成后释放独占锁。
五、实验结果与分析1、进程创建实验结果成功创建新的进程,并能够获取到进程的相关信息。
实验二-实验报告(进程管理)
实验二模拟实现进程管理组长:李和林软件1402一、实验目的1.理解进程的概念,明确进程和程序的区别。
2.理解并发执行的实质。
3.掌握进程的创建,睡眠,撤销等进程控制方法。
二、实验内容用C语言,JAVA语言,C++语言编写程序,模拟实现创建新的进程;查看运行进程,换出某个进程;杀死运行进程。
三、实验准备1.进程的定义进程是程序在一个数据集合上的运行过程,是系统资源分配和调度的一个独立单位。
一个程序在不同的数据集合上运行,乃至一个程序在同样数据集合上的多次运行都是不同的进程。
2.进程的状态通常情况下,一个进程必须具有就绪,执行和阻塞三种基本情况。
1)就绪状态当进程已分配到除处理器外的所有必要资源后,只要再获得处理器就可以立即执行,这时进程的状态就为就绪状态。
在一个系统里,可以有多个进程同时处于就绪状态,通常把这些就绪进程排成一个或多个队列,称为就绪队列。
2)执行状态处于就绪状态的进程一旦获得处理器,就可以运行,进程状态也就处于执行状态,在单处理器系统中,只能有一个进程处于执行状态,在多处理器系统中,则可能有多个进程处于执行状态3)阻塞状态正在执行的进程因为发生某些事件而暂停运行,这种受阻暂停的状态称为阻塞状态,也可称为等待状态。
通常将处于阻塞状态的进程拍成一个队列,称为阻塞队列,在有些系统中,也会按阻塞原因的不同将阻塞状态的进程排成多个队列。
3.进程状态之间的转换4.进程控制块1)进程控制块的作用进程控制块是进程实体的重要组成部分,主要包含下述四个方面的信息:a)进程标示信息b)说明信息c)现场信息d)管理信息5.进程控制块的组织方式1)链接方式2)索引方式6.进程控制原语1)创建原语2)撤销原语3)阻塞原语4)唤醒原语7.程序代码#include<stdio.h>#include<iostream>using namespace std;void clrscr();void create();void run( );void exchange( );//唤出void kill( );void wakeUp( );//唤醒struct process_type{int pid;int priority;//优先次序int size;int state;//状态char info[10];};struct process_type internalMemory[20];int amount=0,hangUp=0,pid,flag=0;//数目,挂起void main( ){int n;int a;n=1;clrscr( );while(n==1){cout<<"\n********************************************";cout<<"\n* 进程演示系统 *";cout<<"\n********************************************";cout<<"\n 1.创建新的进程 2.查看运行进程 ";cout<<"\n 3.换出某个进程 4.杀死运行进程 ";cout<<"\n 5.唤醒某个进程¨ 6.退出系统 ";cout<<"\n*********************************************"<<endl;cout<<"请选择 ";cin>>a;switch(a){case 1:create( );break;case 2:run( );break;case 3:exchange();//换出break;case 4:kill();break;case 5:wakeUp();break;case 6:exit(0);default:n=0;}}}void create(){ //创建进程int i=0;if (amount>=20){cout<<" 内存已满,请先结束或换出进程";}else{for (i=0;i<20;i++){if (internalMemory[i].state==0){break;}}cout<<"请输入新进程的pid: "<<endl;cin>>internalMemory[ i ].pid;cout<<"请输入新进程的优先级: "<<endl;cin>>internalMemory[amount].priority;cout<<"请输入新进程的大小: "<<endl;cin>>internalMemory[amount].size;cout<<"请输入新进程的内容: "<<endl;cin>>internalMemory[amount].info;internalMemory[i].state=1;amount++;}}void clrscr()//清除内存空间{for (int i=0;i<19;i++){internalMemory[i].pid=0;internalMemory[i].priority=0;internalMemory[i].size=0;internalMemory[i].state=0;}amount=0;}void run(){for (int i=0;i<20;i++){if (internalMemory[i].state==1){cout<<"当前内存中的进程:\n"<<endl;cout<<"当前运行的进程: ";cout<<internalMemory[i].pid<<endl;cout<<"当前运行进程的优先级: ";cout<<internalMemory[i].priority<<endl;cout<<"当前运行进程占用的空间大小: ";cout<<internalMemory[i].size;}}}void exchange( ){//唤出优先级最小的进程if (!amount){cout<<"当前没有运行进程\n";return;}cout<<"\n输入换出进程的ID值: ";cin>>pid;for (int i=0;i<20;i++){if (pid==internalMemory[i].pid){if (internalMemory[i].state==1){internalMemory[i].state=2;hangUp++;cout<<"\n已经成功换出进程\n";}else if (internalMemory[i].state==0){cout<<"\n要换出的进程不存在";}else{cout<<"\n要换出的进程已被挂起\n";}flag=1;break;}}if (flag==0){cout<<"\n要换出的进程不存在";}}void kill( ){if (!amount){cout<<"当前没有运行进程\n";return;}cout<<"请输入要杀死的进程: ";cin>>pid;for (int i=0;i<20;i++){if (pid==internalMemory[i].pid){if (internalMemory[i].state==1){internalMemory[i].state=0;amount--;cout<<"此进程被杀死"<<pid;}else if (internalMemory[i].state==0){cout<<"\n要杀死的进程不存在\n";}else{cout<<"\n要杀死的进程已被挂起\n";}flag=1;break;}}if (!flag){cout<<"\n要杀死的进程不存在\n";}}void wakeUp(){if (!amount){cout<<"当前没有运行进程"<<endl;return;}if (!hangUp){cout<<"当前没有挂起进程";return;}cout<<"请输入pid: ";cin>>pid;for (int i=0;i<20;i++){if (pid==internalMemory[i].pid){flag=0;if (internalMemory[i].state==2){internalMemory[i].state=1;hangUp--;cout<<"已经成功唤醒进程\n";}else if (internalMemory[i].state==0){cout<<"\n要换醒的进程不存在\n";}else{cout<<"\n要唤醒的进程已被挂起\n";}break;}}if (flag){cout<<"\n要唤醒的进程已被挂起\n"<<endl;}}8.实现的结果。
操作系统实验报告实验3_1
操作系统实验报告实验3_1一、实验目的本次实验的主要目的是深入理解操作系统中进程管理的相关概念和原理,通过实际操作和观察,掌握进程的创建、调度、同步与互斥等关键机制,提高对操作系统内核工作原理的认知和实践能力。
二、实验环境本次实验在装有 Windows 10 操作系统的计算机上进行,使用了Visual Studio 2019 作为开发工具,编程语言为 C++。
三、实验内容与步骤(一)进程创建1、编写一个简单的 C++程序,使用系统调用创建一个新的进程。
2、在父进程和子进程中分别输出不同的信息,以区分它们的执行逻辑。
```cppinclude <iostream>include <windowsh>int main(){DWORD pid;HANDLE hProcess = CreateProcess(NULL, "childexe", NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pid);if (hProcess!= NULL) {std::cout <<"Parent process: Created child process with PID "<< pid << std::endl;WaitForSingleObject(hProcess, INFINITE);CloseHandle(hProcess);} else {std::cerr <<"Failed to create child process" << std::endl;return 1;}return 0;}```(二)进程调度1、设计一个多进程并发执行的程序,通过设置不同的优先级,观察操作系统对进程的调度情况。
2、记录每个进程的执行时间和等待时间,分析调度算法的效果。
```cppinclude <iostream>include <windowsh>DWORD WINAPI ProcessFunction(LPVOID lpParam) {int priority =(int)lpParam;DWORD start = GetTickCount();std::cout <<"Process with priority "<< priority <<"started" << std::endl;for (int i = 0; i < 100000000; i++){//执行一些计算操作}DWORD end = GetTickCount();DWORD executionTime = end start;std::cout <<"Process with priority "<< priority <<" ended Execution time: "<< executionTime <<" ms" << std::endl;return 0;}int main(){HANDLE hThread1, hThread2;int priority1 = 1, priority2 = 2;hThread1 = CreateThread(NULL, 0, ProcessFunction, &priority1, 0, NULL);hThread2 = CreateThread(NULL, 0, ProcessFunction, &priority2, 0, NULL);if (hThread1!= NULL && hThread2!= NULL) {SetThreadPriority(hThread1, THREAD_PRIORITY_LOWEST);SetThreadPriority(hThread2, THREAD_PRIORITY_NORMAL);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);CloseHandle(hThread1);CloseHandle(hThread2);} else {std::cerr <<"Failed to create threads" << std::endl;return 1;}return 0;}```(三)进程同步与互斥1、实现一个生产者消费者问题的程序,使用信号量来实现进程之间的同步与互斥。
操作系统实验二进程调度
操作系统实验二进程调度摘要:进程调度是操作系统中重要的功能之一,可以决定进程的优先级和执行顺序。
本实验主要介绍了进程调度的概念、不同的调度算法以及如何实现进程调度。
一、概念介绍进程调度是操作系统中的一项重要功能,用于决定哪个进程能够在处理器上运行。
在操作系统中存在多个进程需要同时运行,而处理器资源有限,因此需要通过进程调度来合理地安排进程的执行顺序,提高系统的效率。
进程调度的目标是使系统的吞吐量最大化、响应时间最短、资源利用率最高等。
常见的调度策略包括先来先服务(FCFS)、最短作业优先(SJF)、时间片轮转、优先级调度等。
二、调度算法介绍1.先来先服务(FCFS)先来先服务(FCFS)是最简单的调度算法,按照进程到达的顺序进行调度,先到达的进程先执行。
FCFS算法不考虑进程的优先级和执行时间,容易导致平均等待时间长。
2.最短作业优先(SJF)最短作业优先(SJF)调度算法按照进程所需的CPU时间进行排序,优先调度所需时间最短的进程。
SJF算法可以减少平均等待时间,但可能会导致长作业等待时间过长。
3.时间片轮转时间片轮转是一种抢占式调度策略,将处理器的使用权分割为若干个时间片,每个进程在一个时间片内运行,如果时间片用完仍未运行完,则将该进程放到队列的末尾,并让下一个进程运行。
时间片轮转算法保证了公平性和响应时间,但可能会导致上下文切换次数过多。
4.优先级调度优先级调度是根据进程的优先级进行调度,优先级高的进程先执行。
优先级可以根据进程类型、实时性等因素确定,不同的操作系统可能有不同的优先级范围和策略。
三、实验步骤1.定义进程结构:定义进程结构体,包含进程ID、进程状态、优先级、执行时间等信息。
2.初始化进程队列:将所有进程按照到达的先后顺序加入到进程队列中。
3.实现调度算法:根据不同的调度算法,实现相应的进程调度算法代码。
可以使用循环遍历进程队列,并根据不同的调度策略决定下一个要执行的进程。
4.执行进程调度:在每个时间片结束后,根据调度算法选取下一个要执行的进程,并更新进程的状态和执行时间。
pytest之多进程运行测试用例(pytest-xdist)
pytest之多进程运⾏测试⽤例(pytest-xdist)背景: 我们⽇常的⼯作当中进⾏⾃动化测试编写的测试⽤例会⾮常多,测试⽤例⼀个⼀个的执⾏所需要花费的时间会很长,你想象⼀下如果开发改动⼀块代码,我们需要回归⼀下,这时候执⾏⼀下⾃动化⽤例需要花费⼀⼩时或者好⼏个⼩时的时间,这是我们⽆法容忍的,为了解决这个问题,我们采⽤pytest的插件pytest-xdist来进⾏多进程的并发执⾏测试⽤例,⼤⼤的缩短测试⽤例的执⾏时间,提⾼效率。
并发运⾏测试⽤例:1.安装pytest-xdistpip install pytest-xdist2.多进程并发执⾏测试⽤例pytest test_add.py -n NUM # NUM表⽰并发的进程数举例:项⽬结构如下:代码参考:# file_name: test_a.pyimport pytestimport timedef test_a_01():print("----------------->>> test_a_01")time.sleep(1)assert 1def test_a_02():print("----------------->>> test_a_02")time.sleep(1)assert 1def test_a_03():print("----------------->>> test_a_03")time.sleep(1)assert 1def test_a_04():print("----------------->>> test_a_04")time.sleep(1)assert 1if__name__ == '__main__':pytest.main(["-s", "test_a.py"])# file_name: test_b.pyimport pytestimport timedef test_b_01():print("----------------->>> test_b_01")time.sleep(1)assert 1def test_b_02():print("----------------->>> test_b_02")time.sleep(1)assert 1def test_b_03():print("----------------->>> test_b_03")time.sleep(1)assert 1def test_b_04():print("----------------->>> test_b_04")time.sleep(1)assert 1if__name__ == '__main__':pytest.main(["-s", "test_b.py"])正常运⾏以上代码,耗时:8.09s设置并⾏运⾏数量为4,耗时:3.48s,⼤⼤的缩短了测试⽤例的执⾏时间。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验二 多进程 并发执行
实验目的
• 1、对理论课中学习的进程、程序等的概念作进 对理论课中学习的进程、 一步的理解,明确进程和程序的区别; 一步的理解,明确进程和程序的区别; • 2、加深理解进程并发执行的概念,认识多进程 加深理解进程并发执行的概念, 并发执行的实质; 并发执行的实质; • 3、观察进程争夺资源的现象,分析其过程和原 观察进程争夺资源的现象, 学习解决进程互斥的方法; 因,学习解决进程互斥的方法; • 4、了解Linux系统中多进程之间通过管道通信的 了解Linux系统中多进程之间通过管道通信的 基本原理和应用方法; 基本原理和应用方法; • 5、对经典的多用户、多任务的优先级轮转调度 对经典的多用户、 系统Linux有一定的了解 有一定的了解。 系统Linux有一定的了解。
本课程实验中可能用到的函数
• 1、fork()函数-----进程创建函数。 fork()函数-----进程创建函数 ()函数 进程创建函数。 • 2、getpid()函数-----取得目前进程的进程标识 getpid()函数-----取得目前进程的进程标识 ()函数 码。 • 3、getppid()函数----取得目前进程的父进程的 getppid()函数----取得目前进程的父进程的 ()函数 标识码。 标识码。 • 4、exit()函数----用来正常终结目前进程的执 exit()函数----用来正常终结目前进程的执 ()函数 行。 • 5、pipe()函数----建立管道函数, pipe()函数----建立管道函数 ()函数 建立管道函数, • 6、read()函数、write()函数、lockf()函 read()函数、write()函数、lockf() ()函数 ()函数 ()函 数
阅读/usr/include/sched.h源代码 阅读/usr/include/sched.h源代码
多进程并发实例
结
束
• 7、perror(const char *s)函数----用来将上一个 perror( *s)函数----用来将上一个 函数发生错误的原因输出到标准错误(stderr)。 函数发生错误的原因输出到标准错误(stderr)。 • 8、isascii(int c)函数---检查c是否为ASCII码字 isascii( c)函数---检查 是否为ASCII码字 检查c 也就是判断c的范围是否为0 符,也就是判断c的范围是否为0~127. • 9、isupper()函数----检查参数c是否为大写英 isupper()函数----检查参数 ()函数 检查参数c 文字母。 文字母。 • 10、islower()函数----检查参数c是否为小写英 10、islower()函数----检查参数 ()函数 检查参数c 文字母, 文字母, • 11、toupper()函数----若参数c为小写字母则将 11、toupper()函数----若参数 ()函数 若参数c 对应的大写字母返回, 对应的大写字母返回,返回值为转换后的大写字 若不需转换则将参数c值返回。 母,若不需转换则将参数c值返回。