操作系统实验

实验一 命令解释程序

实验内容

利用C语言编写一个微型命令解释程序minishell.c,该程序可接收并解释以下命令:
(1) dir 列出当前目录
(2) cop file1 file2 拷贝文件
(3) era filename 删除文件
(4) disp string 显示字符串
(5) end 结束,退出
要求:
(1)检查命令的合法性,如果有错误,显示出错信息,等待重新输入;
(2)命令前后有空格示为合法命令。

实验预备内容

  • gets() 读入字符串,直到回车结束,但是不包括回车
  • strcspn(str1,str2) 返回str1开头连续不包含str2的字符串
  • strncpy(str1,str2,n) 将str2字符串的前n个复制到str1中
  • strcmp(str1,str2) 将str1和str2进行比较
    • 返回值小于0,str1 < str2
    • 等于零 str1 == str2
    • 大于零 str1 > str2
  • system(command) 执行command

示例程序

#define true 1
#define false 0

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
   
    char cmdl[80];
    char *scwt[] = {
   "exit","dir","time"};
    static int cmdnum = 3;  // 可用命令数
    char cmd[80];
    int j,n;

    while(true){
   
        printf("Please input command:");
        gets(cmdl); // 取命令行输入
        n = strcspn(cmdl," ");// 取命令部分
        if(n > 0 || strlen(cmdl) > 0){
   
            strncpy(cmd,cmdl,n);
            // 构成字符串
            cmd[n] = '\0';
            for(j = 0;j < cmdnum;j++){
   
                if(strcmp(cmdl,scwt[j]) == 0) break;
            }
            if(j == 0) exit(0);
            if(j < cmdnum){
   
                system(cmdl);
                continue;
            }
            printf("Bad command!\n");
        }
    }
}

实验代码

暂时先不放出来
在这里插入图片描述

实验二 进程管理

实验内容
1、进程的创建
编写一段程序,使用系统调用fork()创建两个子进程。让父进程显示字符串‘Parent:’;两个子进程分别显示字符串‘Child1:’和‘Child2:’。多次运行此程序,观察屏幕显示的结果,并分析原因。
2、进程控制
修改已编写的程序,将输出多次重复的一句话,观察程序执行时在屏幕上显示的结果,并分析原因。
若在程序中使用系统调用lockf()来给每一个进程加锁,可以实现进程之间的互斥,观察屏幕显示的结果,并分析原因。

实验预备内容和示例程序

fork 的测试

fork的功能描述:

  • fork()通过复制进程来创建一个新进程。子进程类似于当前进程的副本,但是:
    • 子进程有自己唯一的进程ID,而且这个进程的PID与任何进程的ID都不相同
    • 子进程的父进程ID等于父进程的进程ID
  • 返回值:
    • 如果成功,在父进程中返回子进程的PID,在子进程中返回0
    • 失败了,在父进程中返回-1,没有创建子进程
crescent_p@CP:~/Program/Experiment2$ gcc -o fork1 forkTest1.c 
crescent_p@CP:~/Program/Experiment2$ ./fork1 
fork test
fork test
#include <stdio.h>
#include <unistd.h>

int main(){
   
	fork();
	printf("fork test\n");
	return  0;
}

分析:为什么输出了两次?

  • 程序运行开始就创建了一个进程
  • 当进程执行fork之后,创建了一个子进程
    • 子进程的代码是父进程代码的副本
    • 子进程的代码执行进度和父进程创建子进程时代码执行进度一致

测试二:

#include <stdio.h>
#include <unistd.h>

int main(){
   
	pid_t pid;
	pid = fork();
	// 父进程
	if(pid > 0){
   
		printf("I am father\n");
	}
	if(pid == 0){
   
		printf("I an son\n");
	}
	if(pid < 0){
   
		printf("fork error\n");
	}
	printf("main over\n");
	return 0;
}

image-20210928193608909

分析为什么结果不一样:

  • 为什么又会出现son又会出现father?
    • 在父进程中,fork()返回子进程的PID,大于0,因此会执行第一个if
    • 在子进程中,fork()返回子进程的PID,等于0,因此会执行第二个if
  • 为什么两次执行这个可执行文件结果不一样?
    • 进程的异步性,我们设父进程为p1,子进程为p2
    • 第一个执行:
      • p1执行完第一个if,就轮到p2上处理机运行
    • 第二个执行:
      • p1执行完,才轮到p2上处理机

测试三:

#include <stdio.h>
#include <unistd.h>

int main(){
   
	printf("执行到fork函数之前其进程为 %d,其父进程为 %d\n",getpid(),getppid());
	sleep(1);
	fork();
	printf("这个进程id为:%d,它的父进程为%d\n",getpid(),getppid());
	return 0;
}

在这里插入图片描述
测试四:

#include <stdio.h>
#include <unistd.h>
int main(){
   
	pid_t p1,p2;
	while((p1 = fork()) == -1);
	// 子进程
	if(p1 == 0) {
    
		puts("b");
	}
	else {
   
		puts("a");
	}
	return 0;
}

实验代码

暂时先不放出来
image-20210928200118428
image-20210928202915931
image-20210928203604575

实验三进程间的通信

管道通信

实验预备内容和示例程序

测试 pipe():

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>


int main(){
   
    pid_t pid;
    int fd[2];
    char buf[50],s[50];
    // 创建了管道,半双工
    pipe(fd);
    while((pid = fork()) == -1);
    // 子进程
    if(pid == 0){
   
        sprintf(buf,"Child is sending message!");
        // fd[1] 写入管道
        write(fd[1],buf,50);
        // exit 在退出前,还会把文件缓冲区中的内容写回文件
        // 退出进程,其实是变成了一个僵尸进程
        exit(0);
    }else{
   
        // 进程一旦调用了wait,就立即阻塞自己
        // 由wait自动分析是否当前进程的某个子进程已经退出
        // 如果让它找到了这样一个已经变成僵尸的子进程
        // wait就会收集这个子进程的信息,并把它彻底销毁后返回
        // 如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
        wait(0);
        // fd[0] 读取管道,将管道中的内容读入到s中
        read(fd[0],s,50);
        printf("%s\n",s
  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值