实验一: 进程的创建与同步
进程初识实验报告

一、实验目的通过本次实验,使学生了解进程的基本概念,掌握进程的创建、调度、同步与互斥等基本操作,加深对操作系统进程管理的理解。
二、实验环境操作系统:Linux编程语言:C开发工具:gcc三、实验内容本次实验主要包含以下内容:1. 进程的创建与终止2. 进程的调度3. 进程的同步与互斥4. 守护进程的创建四、实验步骤1. 进程的创建与终止(1)使用 `fork()` 函数创建进程。
`fork()` 函数返回值:- 在父进程中,返回新创建子进程的进程ID;- 在子进程中,返回0。
(2)使用 `wait()` 或 `waitpid()` 函数等待子进程结束。
`wait()` 函数返回子进程的终止状态。
(3)使用 `exit()` 函数终止进程。
2. 进程的调度(1)进程调度算法:时间片轮转算法(RR)、优先级调度算法。
(2)使用 `sleep()` 函数模拟进程运行时间。
3. 进程的同步与互斥(1)使用信号量(semaphore)实现进程同步。
(2)使用互斥锁(mutex)实现进程互斥。
4. 守护进程的创建(1)使用 `fork()` 函数创建子进程。
(2)在子进程中,使用 `setsid()` 函数创建新的会话,使子进程成为守护进程。
(3)父进程退出,守护进程继续运行。
五、实验代码示例```c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#include <sys/types.h>#include <signal.h>#define SEM_NAME "/sem"int main() {pid_t pid;int semid, semnum;struct sembuf sem_op;// 创建信号量集semid = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);if (semid == -1) {perror("semget");exit(1);}// 初始化信号量semnum = 0;sem_op.sem_num = semnum;sem_op.sem_op = 1;sem_op.sem_flg = 0;if (semctl(semid, semnum, SETVAL, sem_op) == -1) { perror("semctl");exit(1);}// 创建子进程pid = fork();if (pid == 0) {// 子进程printf("Child process: %d\n", getpid());sem_op.sem_op = -1; // P操作if (semop(semid, &sem_op, 1) == -1) {perror("semop");exit(1);}printf("Child process: acquired semaphore\n");sleep(5); // 模拟子进程运行时间sem_op.sem_op = 1; // V操作if (semop(semid, &sem_op, 1) == -1) {perror("semop");exit(1);}printf("Child process: released semaphore\n"); exit(0);} else if (pid > 0) {// 父进程printf("Parent process: %d\n", getpid());sem_op.sem_op = -1; // P操作if (semop(semid, &sem_op, 1) == -1) {perror("semop");exit(1);}printf("Parent process: acquired semaphore\n"); sleep(5); // 模拟父进程运行时间sem_op.sem_op = 1; // V操作if (semop(semid, &sem_op, 1) == -1) {perror("semop");exit(1);}printf("Parent process: released semaphore\n");wait(NULL); // 等待子进程结束} else {perror("fork");exit(1);}// 删除信号量集if (semctl(semid, 0, IPC_RMID) == -1) {perror("semctl");exit(1);}return 0;}```六、实验结果与分析1. 通过实验,加深了对进程的基本概念和操作的理解。
进程的创建实验报告

进程的创建实验报告进程的创建实验报告引言:在计算机科学领域中,进程是一个非常重要的概念。
进程是计算机程序的执行实例,它具有独立的内存空间和执行环境。
进程的创建是操作系统中一个关键的操作,本实验旨在通过编写一个简单的程序来演示进程的创建过程。
实验目的:通过实验,我们的目标是深入理解进程的创建过程,并了解操作系统是如何管理进程的。
实验步骤:1. 引入必要的头文件:在开始编写代码之前,我们需要引入一些必要的头文件。
这些头文件包括<sys/types.h>、<sys/wait.h>和<unistd.h>。
这些头文件提供了创建进程所需的函数和数据类型。
2. 创建一个子进程:在主程序中,我们使用fork()函数来创建一个子进程。
fork()函数会在当前进程的基础上创建一个新的进程,这个新进程称为子进程。
子进程和父进程几乎完全相同,只有在返回值上有所区别。
如果fork()函数返回0,表示当前进程是子进程;如果返回一个正整数,表示当前进程是父进程。
3. 子进程的执行:在子进程中,我们可以编写任意的代码来执行特定的任务。
子进程可以使用exec()函数来执行其他程序,或者执行一系列的操作。
在本实验中,我们简单地输出一条信息,以展示子进程的执行过程。
4. 父进程的执行:在父进程中,我们可以编写代码来执行其他任务,或者等待子进程的结束。
在本实验中,我们使用wait()函数来等待子进程的结束。
wait()函数会暂停父进程的执行,直到子进程结束为止。
5. 编译和运行程序:在完成代码编写后,我们需要将程序编译成可执行文件,并运行它。
我们可以使用gcc编译器来编译程序,然后运行生成的可执行文件。
实验结果:在运行程序后,我们可以观察到以下结果:子进程开始执行。
父进程等待子进程结束。
子进程结束。
父进程继续执行。
结论:通过本实验,我们成功地演示了进程的创建过程。
我们了解了操作系统是如何管理进程,并且掌握了使用fork()函数来创建子进程的方法。
实验1编程实现进程同步和互斥

实验1编程实现进程同步和互斥进程(线程)同步和互斥是操作系统中非常重要的概念,它们用于控制多个进程(线程)之间的访问顺序,以确保数据的一致性和正确性。
在本文中,我们将详细介绍进程(线程)同步和互斥的概念,并通过编程实现来说明它们的具体应用。
1.进程(线程)同步的概念进程(线程)同步是指多个进程(线程)之间按照一定的顺序访问共享的资源,以避免竞争条件(race condition)和数据不一致的问题。
在并发环境下,多个进程(线程)同时访问共享的资源时,可能会遇到互相干扰的情况,导致程序的执行结果出现错误。
2.进程(线程)互斥的概念进程(线程)互斥是指在同一时间只能有一个进程(线程)对共享资源进行访问,其他进程(线程)必须等待当前进程(线程)释放资源后才能访问。
通过引入互斥机制,可以避免多个进程(线程)同时对共享资源进行写操作,从而保证数据的一致性和正确性。
3.进程(线程)同步和互斥的实现在实际编程中,可以通过各种同步和互斥机制来实现进程(线程)同步和互斥。
常见的机制有信号量(Semaphore)、互斥锁(Mutex)、条件变量(Condition Variable)等。
下面我们将通过一个简单的编程实例来演示如何使用信号量和互斥锁实现进程(线程)同步和互斥。
假设有两个线程,线程A负责打印奇数,线程B负责打印偶数,要求线程A和线程B交替打印1-100的数字。
我们可以使用互斥锁来控制两个线程的访问顺序,使用信号量来控制线程A和线程B的打印顺序。
首先,我们定义一个全局变量num,用来记录当前需要打印的数字。
定义一个互斥锁mutex,用来保护对num的访问。
定义一个信号量sem,用来控制线程A和线程B的打印顺序。
初始时,num为1,mutex为未锁定状态,sem的初始值为0。
线程A的处理函数如下:```void* threadA(void* arg)while (num <= 100)//等待信号量semsem_wait(&sem);//加锁pthread_mutex_lock(&mutex);//打印奇数if (num <= 100)printf("%d\n", num);num += 2;}//解锁pthread_mutex_unlock(&mutex);//发送信号量给线程Bsem_post(&sem);}return NULL;```线程B的处理函数如下:```void* threadB(void* arg)while (num <= 100)//等待信号量semsem_wait(&sem);//加锁pthread_mutex_lock(&mutex);//打印偶数if (num <= 100)printf("%d\n", num);num += 2;}//解锁pthread_mutex_unlock(&mutex);//发送信号量给线程Asem_post(&sem);}return NULL;```在主函数中创建两个线程,并执行线程:```int maipthread_t tidA, tidB;//初始化互斥锁pthread_mutex_init(&mutex, NULL);//初始化信号量sem_init(&sem, 0, 1);//创建线程Apthread_create(&tidA, NULL, threadA, NULL); //创建线程Bpthread_create(&tidB, NULL, threadB, NULL);//等待线程A结束pthread_join(tidA, NULL);//等待线程B结束pthread_join(tidB, NULL);//销毁互斥锁pthread_mutex_destroy(&mutex);//销毁信号量sem_destroy(&sem);return 0;```通过运行以上代码,我们可以看到线程A和线程B会交替打印1-100的数字,实现了进程(线程)的同步和互斥。
Linux进程创建与进程通信实验指导书

实验一、Linux进程创建与进程通信实验目的1. 熟悉有关Linux系统调用;2. 学习有关Linux的进程创建,理解进程创建后两个并发进程的执行;3. 通过系统调用wait()和exit(),实现父子进程同步;4. 掌握管道、消息缓冲等进程通信方法并了解其特点和使用限制。
实验内容1. 父进程创建子进程实现父进程创建一个子进程,返回后父子进程分别循环输出字符串“The parent process.”及“The child process.”5次,每次输出后使用sleep(1)延时一秒,然后再进入下一次循环。
给出源程序代码和运行结果。
2. 父子进程同步修改上题程序,使用exit()和wait()实现父子进程同步,其同步方式为父进程等待子进程的同步,即:子进程循环输出5次,然后父进程再循环输出5次。
给出源程序代码和运行结果。
3. Linux管道通信编写一个程序,实现以下功能。
给出源程序代码和运行结果。
(1)父进程使用系统调用pipe()创建一个无名管道;(2)创建两个子进程,分别向管道发送一条信息后结束;子进程1发送:Child 1 is sending a message to parent!子进程2发送:Child 2 is sending a message to parent!(3)父进程从管道中分别接收两个子进程发来的消息并显示在屏幕上,父进程结束。
两个子进程发送信息没有先后顺序要求。
4. Linux消息缓冲通信编写一个程序,实现以下功能。
给出源程序代码和运行结果。
(1)父进程创建一个消息队列和一个子进程,由子进程发送消息,父进程等待子进程结束后接收子进程发来的消息,并显示消息内容。
以“end”作为结束消息。
(2)分别编写发送进程和接收进程,由发送进程发送消息,接收进程接收消息。
采用先执行发送进程后执行接收进程的方式同步。
以“end”作为结束消息。
(3)模拟C/S通信,要求如下。
(选做)①模拟客户端(client端)程序client,其功能如下。
操作系统实验一-进程同步

实验一进程同步一、实验目的:分析进程的同步与互斥现象,编程实现经典的进程同步问题——生产者与消费者问题的模拟,进一步加深对进程同步与互斥的理解。
二、实验内容:用C语言实现对生产者与消费者问题的模拟。
实验原理:生产者和消费者是经典的进程同步问题,在这个问题中,生产者不断的向缓冲区中写入数据,而消费者则从缓冲区中读取数据。
生产者进程和消费者对缓冲区的操作是互斥,即当前只能有一个进程对这个缓冲区进行操作,生产者进入操作缓冲区之前,先要看缓冲区是否已满,如果缓冲区已满,则它必须等待消费者进程将数据取出才能写入数据,同样的,消费者进程从缓冲区读取数据之前,也要判断缓冲区是否为空,如果为空,则必须等待生产者进程写入数据才能读取数据。
三、实验准备:1. 实现步骤:(1)分析计算机系统中对资源的分配与释放过程:计算机系统中的每个进程都可以消费或生产某类资源。
当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
而当某个进程释放资源时,则它就相当一个生产者。
(2)定义生产者消费者问题中的各数据结构,并初始化信号量;(3)创建生产者与消费者进程,利用信号量实现生产者与消费者之间的同步与互斥;最后编程实现。
2. 相关函数:在实现的过程中需要用到以下API函数:(1)CreateThread()//该函数创建一个在调用进程的地址空间中执行的线程。
若线程创建成功,将返回该线程的句柄。
函数原型:HANDLE CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes, //描述安全性,用NULL表示使用缺省值DWORD dwStackSize, //新线程拥有自己的堆栈,0表示使用缺省值1MB,推荐LPTHREAD_START_ROUTINE lpStartAddress, //新线程的起始地址,放线程函数名称LPVOID lpParameter,//此值被传送到线程函数去作为参数DWORD dwCreationFlags,//允许产生一个暂时挂起的线程,默认是0立即开始执行LPDWORD lpThreadld );//新线程的ID被传到这用法举例:hHandle1 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,0,(LPTHREAD_START_ROUTINE) ThreadName1,(LPVOID) NULL,0, &dwThreadID1 );(2)CreateMutex()函数可用来创建一个有名或无名的互斥量对象,函数返回值为互斥对象的句柄。
进程同步实验报告

一、实验目的1. 理解进程同步的概念和原理;2. 掌握进程同步的基本方法和机制;3. 学会使用信号量实现进程同步;4. 通过实验验证进程同步机制的有效性。
二、实验原理1. 进程同步:在多道程序设计中,进程的执行是并发的,但某些情况下需要保证多个进程按照一定的顺序执行,以避免出现数据不一致、死锁等问题。
进程同步是指通过某种机制,协调多个进程的执行顺序,保证它们能够正确、有效地共享资源。
2. 信号量:信号量是一种特殊的变量,用于实现进程同步。
信号量具有两个原子操作:P操作(wait)和V操作(signal)。
P操作用于申请资源,V操作用于释放资源。
3. 互斥锁:互斥锁是一种常见的进程同步机制,用于保证临界资源的互斥访问。
当一个进程进入临界区时,它会尝试获取互斥锁,如果锁已被其他进程获取,则该进程进入等待状态;当进程退出临界区时,它会释放互斥锁。
三、实验内容1. 实验环境:Linux操作系统,C语言编程环境。
2. 实验工具:gcc编译器、gdb调试器。
3. 实验步骤:(1)创建一个互斥锁,用于保护临界资源。
(2)编写两个进程,分别模拟对临界资源的访问。
(3)在进程访问临界资源前,使用P操作尝试获取互斥锁。
(4)在进程访问临界资源后,使用V操作释放互斥锁。
(5)编译并运行程序,观察进程执行情况。
四、实验结果与分析1. 实验结果:(1)在互斥锁的保护下,两个进程能够按照预期顺序访问临界资源。
(2)当其中一个进程正在访问临界资源时,另一个进程会进入等待状态。
(3)当进程访问临界资源完成后,它会释放互斥锁,允许其他进程访问。
2. 实验分析:(1)互斥锁能够有效地保护临界资源,避免数据不一致问题。
(2)信号量P操作和V操作保证了进程的同步,避免了死锁现象。
(3)通过实验验证了进程同步机制的有效性。
五、实验总结本次实验通过使用信号量和互斥锁,实现了进程同步。
实验结果表明,信号量和互斥锁能够有效地保证进程按照预期顺序执行,避免数据不一致和死锁等问题。
实验一进程创建 Linux实验报告

实验一进程创建【实验目的和要求】1、1.了解进程的概念及意义;2.了解子进程和父进程;3.掌握创建进程的方法。
【实验内容】1、1.子进程和父进程的创建;2.编写附件中的程序实例;3.撰写实验报告。
【实验原理】1、原型:#include <unistd.h>pid_t fork(void);在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。
新进程为子进程,而原进程为父进程。
fork函数创建子进程的过程为:使用fork函数得到的子进程是父进程的一个复制品,它从父进程继承了进程的地址空间,包括进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端,而子进程所独有的只有它的进程号、资源使用和计时器等。
通过这种复制方式创建出子进程后,原有进程和子进程都从函数fork返回,各自继续往下运行,但是原进程的fork返回值与子进程的fork返回值不同,在原进程中,fork返回子进程的pid,而在子进程中,fork返回0,如果fork返回负值,表示创建子进程失败。
子进程和父进程继续执行fork调用之后的指令。
子进程是父进程的副本。
例如,子进程获得父进程数据空间、堆和栈的副本。
注意,这是子进程所有用的副本。
父进程和子进程并不共享这些存储空间部分。
父进程和子进程共享正文段。
2、原型:#include <unistd.h>pid_t vfork(void);vfork函数的调用序列和返回值与fork相同,但两者的语义不同。
vfork函数用于创建一个新进程,而该进程的目的是exec一个新程序。
vfork不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec,它在父进程的空间中运行。
vfork保证子进程先运行,在它调用exit之后父进程才可能被调度运行,当子进程调用这两个函数中的任意一个时,父进程会恢复运行。
进程的管理实验报告

一、实验目的1. 理解进程的基本概念和进程状态转换过程。
2. 掌握进程创建、进程同步和进程通信的方法。
3. 了解进程调度算法的基本原理和实现方法。
4. 通过实验加深对进程管理的理解,提高操作系统实践能力。
二、实验环境1. 操作系统:Linux2. 编程语言:C/C++3. 开发工具:GCC三、实验内容1. 进程创建与状态转换(1)使用fork()函数创建一个子进程,并观察父进程和子进程的进程ID。
(2)使用exec()函数替换子进程的映像,实现进程的创建。
(3)观察进程状态转换过程,如创建、运行、阻塞、就绪、终止等。
2. 进程同步(1)使用互斥锁(mutex)实现进程的互斥访问共享资源。
(2)使用信号量(semaphore)实现进程的同步,如生产者-消费者问题。
(3)观察进程同步的效果,确保进程安全执行。
3. 进程通信(1)使用管道(pipe)实现进程间的单向通信。
(2)使用消息队列(message queue)实现进程间的双向通信。
(3)使用共享内存(shared memory)实现进程间的快速通信。
(4)观察进程通信的效果,确保数据正确传递。
(1)实现基于优先级的进程调度算法,如先来先服务(FCFS)和最高优先级优先(HPF)。
(2)实现基于时间片的轮转调度算法(RR)。
(3)观察进程调度算法的效果,分析不同算法的优缺点。
四、实验步骤1. 编写程序实现进程创建与状态转换,使用fork()和exec()函数。
2. 编写程序实现进程同步,使用互斥锁和信号量。
3. 编写程序实现进程通信,使用管道、消息队列和共享内存。
4. 编写程序实现进程调度,使用优先级调度和时间片轮转调度。
5. 编译并运行程序,观察实验结果,分析实验现象。
五、实验结果与分析1. 进程创建与状态转换通过实验,我们成功创建了父进程和子进程,并观察到进程ID的变化。
在进程创建过程中,父进程的进程ID与子进程的进程ID不同,说明子进程是独立于父进程的实体。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验一:进程的创建与同步1实验目的(1) 熟悉Windows系统提供的进程创建与同步。
(2) 掌握Windows系统环境下进程的创建与撤销方法。
2 进程创建2.1结构体模拟进程PCBtypedef struct pcb{int num;struct pcb *next;int priority;int timeneed;int state;}pcb;/*用此结构体来模拟一个进程*/2.2 随机产生进程运行的优先级与运行时间srand((unsigned int)time(NULL));for(i=1;i<=n;i++)/*用循环来创建指定个结点*/{//q=(pcb *)malloc(sizeof(pcb));p->next=q;q->num=i;q->next=NULL;q->priority=1+(10*rand()/(RAND_MAX+1.0));/*随机产生优先级*/q->timeneed=1+(100*rand()/(RAND_MAX+1.0));/*随机产生运行时间*/q->state=WAIT;p=q;}3 进程的执行和调度void control()/*此函数是用来控制各个进程的执行和调度*/if(run->timeneed>10) /*进程需要时间减少*/run->timeneed=run->timeneed-run->timeneed/10;elserun->timeneed--;run->priority=run->priority-1;/*进程优先级减1*/if(run->priority<=head->next->priority)/*如果当前运行的进程的优先级低于队首进程的优先级*/{ run->state=WAIT;run=getmaxpriority(head);/*则从进程队列中挑选一个优先级最大的进程来运行*/run->state=RUN;}4 进程删除void delect(struct pcb *head,struct pcb *run)/*此函数用来将运行完成的进程删除出进程队列*/5实验总结……6源程序框架#include"stdio.h"#include"stdlib.h"#include "string.h"#include "ctime"#include <iostream>#include<windows.h>#define WAIT 1#define RUN 2#define FINISH 3using namespace std;typedef struct pcb{int num;struct pcb *next;int priority;int timeneed;int state;}pcb;/*用此结构体来模拟一个进程*/struct pcb *head;struct pcb *run;pcb *jccreat(int n)/*此函数用于创建进程队列*/{int i=1;pcb *head,*p,*q;head=(pcb *)malloc(sizeof(pcb));/*创建一个空表头*/p=head;srand((unsigned int)time(NULL));//for(i=1;i<=n;i++)/*用循环来创建指定个结点*/{q=(pcb *)malloc(sizeof(pcb));p->next=q;q->num=i;q->next=NULL;q->priority=1+(10*rand()/(RAND_MAX+1.0));/*随机产生优先级*/q->timeneed=1+(100*rand()/(RAND_MAX+1.0));/*随机产生运行时间*/q->state=WAIT;p=q;}return head;/*返回表头指针*/}pcb *getmaxpriority(struct pcb *head)/*此函数用来挑选一个优先级最大的进程来执行*/ {struct pcb *p,*q;int max;p=head->next;max=p->priority;/*初始max为队首结点的优先级*/q=p;while(p){if(p->priority>max)/*逐一比较,选出优先级最大的结点*/{max=p->priority;q=p;}//?p=p->next;}return q;}void delete1(struct pcb *head,struct pcb *run)/*此函数用来将运行完的进程删除出进程队列*/ {struct pcb *q=head;while(q->next)/*扫描进程队列,找到执行完了的进程*/{if(q->next->num==run->num)/*判断是不是已完成的进程*/{if(run->next!=NULL)q->next=run->next;else q->next=NULL;free(run);/*释放申请的空间*/return;}q=q->next;}}int i=0;void control()/*此函数是用来控制各个进程的执行和调度*/{struct pcb *p;run=head->next;/*初始让第一个进程运行*/run->state=RUN;while(run){if(run->timeneed>0)/*如果当前run指针指向的进程所需时间不为零,状态为运行状态,就让这个进程运行*/if(run->state==RUN){printf("pcb %d is running.\n",run->num);printf("Waiting list:");/*显示整个等待队列*/p=head->next;while(p){if(p!=run)printf("pcb%d ",p->num);p=p->next;}printf("\n");Sleep(500);/*模拟进程运行*/if(run->timeneed>10)run->timeneed=run->timeneed-run->timeneed/10;/*进程需要时间减少*/elserun->timeneed--;run->priority=run->priority-1;/*进程优先级减1*/cout<<run->timeneed;cout<<"\t";cout<<run->priority;cout<<"\n";if(i==5){ i=0;getchar();}elsei++;}if(run->timeneed!=0){if(run!=getmaxpriority(head))/*如果当前运行进程的优先级不等于队列中最大的进程优先级*///if(run->priority<getmaxpriority(head)->priority)//作用不同{ run->state=WAIT;run=getmaxpriority(head);/*则从进程队列中挑选一个优先级最大的进程来运行*/run->state=RUN;}}else{ printf("pcb %d is finished.\n",run->num);Sleep(500);delete1(head,run);/*删除该结点*/if(head->next!=NULL)/*判断进程队列是不是为空*/{run=head->next;run->state=RUN;}else{printf("All progresses are done.\n");return;}}}}main(){int n;int flag=1;printf("Enter the number of the progresses:");scanf("%d",&n);/*输入要创建的进程的数量*/head=jccreat(n);/*创建进程队列,将链表的表头赋给head指针*/run=head->next;/*run指针指向正在运行的进程的pcb*/while(run){printf("num: %d ,priority: %d ,timeneeds: %d\n",run->num,run->priority,run->timeneed);run=run->next;} /*将刚创建的进程队列打印出来*/while(flag)/*由flag的值判断是否继续执行control()函数*/{if(head->next)/*判断进程是否完成*/control();else flag=0;}getchar();}7 实验内容改进:●在进程结构中增加进程到达时间;●增加信号量机制,设置不同的进程的运行时序关系,通过PV操作实现同步;●使用信号量使两个进程实现互斥运行。