首页 > 其他分享 >os实训课程模拟考试(大题复习)

os实训课程模拟考试(大题复习)

时间:2024-06-30 18:28:18浏览次数:3  
标签:mutex 函数 int buffer fd 实训 printf 模拟考试 os

目录

一、Linux操作系统

(1)第1关:Linux初体验 

(2)第2关:Linux常用命令

(3)第3关:Linux 查询命令帮助语句

二、Linux之进程管理—(重点)

(1)第1关:获取进程常见属性

(2)第2关:进程创建操作-fork

(3)第3关:进程创建操作-vfork

(4)第4关:进程终止

三、生产者消费者问题实践

(1)第1关:生产者消费者问题实践

(2)第2关:进程互斥和同步

四、基于信号量的进程间通信

(1)第1关:信号量IPC操作考查

五、基于命名管道与信号的进程间通信

(1)第1关:命名管道与信号IPC操作考查

六、 Linux vi/vim编辑器(难度:简单)

(1)第1关:vi/vim基本用法

(2)第2关:vi/vim工作模式切换

(3)第3关:vi/vim命令模式

(4)第4关:vi/vim底线命令模式(重点)

七、读文件系统函数(难度:简单)

(1)第1关:读文件系统函数

八、写文件系统函数(难度:中等)

(1)第1关:写文件系统函数

 九、进程基础操作(难度:简单)

(1)第1关:进程基础操作考察


本篇博客的主要内容是在做大题时遇到的问题和一些总结。(具体答案看我之前的博客)

一、Linux操作系统

(1)第1关:Linux初体验 

(2)第2关:Linux常用命令
  • newfile文件复制一份到newdir目录下并命名为newfileCpy
  • cp newfile newdir/newfileCpy

(3)第3关:Linux 查询命令帮助语句
  • linux中使用man命令来查询命令的帮助文件

二、Linux之进程管理—(重点)

(1)第1关:获取进程常见属性
  • 获取进程本身的进程ID的系统调用函数是getpid()
  • 获取父进程的进程ID的系统调用函数是getppid()。
(2)第2关:进程创建操作-fork
  • 这题需要注意的地方:pid_t pid =fork();
(3)第3关:进程创建操作-vfork
  • 这题需要注意的地方:pid_t pid = vfork();
  • 子进程中输出"Children"字符串(提示:需要换行)
(4)第4关:进程终止
  • 用这个注册函数:atexit()on_exit()调用成功返回0;调用失败返回一个非零值。
 void exit(){
        printf("%d",getpid());
    }
	if(atexit(exit)){
        
    }

三、生产者消费者问题实践

(1)第1关:生产者消费者问题实践
  • 观察题目代码给出的生产者函数。根据这个来写!!
  • sem_t empty; :类似等待一个信号(生产)

  • sem_t full; :类似等待一个信号(消费)

  • sem_wait(&empty);
  • sem_wait(&full);

    (在每一个操作时和释放时都要记得加锁和解锁)

  • 加锁 pthread_mutex_lock(&mutex);
  • 释放锁 pthread_mutex_unlock(&mutex);

锁对象:pthread_mutex_t mutex;


  • 设置一个参数(仿照生产者函数)int nextc = 0;
  • 先给一个等待消费条件:sem_wait(&full);
  • 再加锁:pthread_mutex_lock(&mutex);
  • 意思是:从之前生产了的东西拿东西出来消费:nextc=buffer[out];

  • 与生产者函数中用到的一样:int out = 0;

  • 这个跟着改:printf("Consume one message:%d\n", nextc);

  • fflush(stdout);  //printf后请一定调用这句刷新输出缓存out = (out + 1) % SIZE;

  • out = (out + 1) % SIZE; (这个跟生产者函数一样,对着改就行)
  • pthread_mutex_unlock(&mutex);   ——> 再解锁

最后记得给一个消费完的信号:sem_post(&empty); 。意思其实就是消费完,给一个叫"空"的信号。


具体的答案《消费:Consumer()函数》

void *Consumer()
{
    // ============================= begin ======================

	//请补充消费者线程函数代码
    int nextc = 0;
    int i = 0;
	for(; i < 10; ++i)
	{  
		int time = rand() % 10 + 1;
        usleep(time*100000); 
        sem_wait(&full); 
		pthread_mutex_lock(&mutex);
		nextc=buffer[out];
		printf("Consume one message:%d\n", nextc);
		fflush(stdout);//printf后请一定调用这句刷新输出缓存
		out = (out + 1) % SIZE;
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&empty);
	}


 // ============================= end ========================

}

对比题目提供的《生产函数:Producer()》

int in = 0;
int out = 0;
int buffer[SIZE];
sem_t empty;
sem_t full;
pthread_mutex_t mutex;

void *Producer()
{
    int nextp = 0;
    int i = 0;
	for(; i < 10; ++i)
	{  
		int time = rand() % 10 + 1;
        usleep(time*100000); 
        sem_wait(&empty); 
		pthread_mutex_lock(&mutex);
		buffer[in] = nextc;
		printf("Produce one message:%d\n", nextp);
		fflush(stdout);//printf后请一定调用这句刷新输出缓存
		in = (in + 1) % SIZE;
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&full);
	}
}
(2)第2关:进程互斥和同步

(这个就简单了!!结合上面学的东西,以及仿照这个题目女儿的"苹果"消费函数写就好)

  • 把消费等待的信号换成"orange(桔子)"
  • 把printf(....)输出换一下就好了
  • 儿子消费函数答案
void *Son()
{
    // ============================== begin ===========================

	//请添加儿子线程的函数代码
    while(1)
	{
		int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒
		usleep(time * 100000);        
		sem_wait(&orange); 
		pthread_mutex_lock(&mutex);
		printf("儿子取了一个桔子\n") ;
        fflush(stdout);
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&empty);
	}

    // ============================== end ==============================
}

四、基于信号量的进程间通信

(1)第1关:信号量IPC操作考查
  • 搞清楚函数:semctl(int semid,int semnum,int cmd,...);
  • semid要操作的信号量集合:(题目中给出变量:"int semid;")
  • semnum集合中信号量的编号(题目中就是:"i")
  • cmd执行的操作:(题目中有提示:#define GETVAL 获取信号量的值返回信号的值

具体答案如下:

(此代码不严谨!!因为没有判断是否函数调用成功!但是满足评测要求)

 for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
    {
        // =================================== begin ===============================

        /*请调用semctl函数,读取并输出与上述数组输出相同的输出*/
 
        // 注意:getval_arg.val 在这里不需要设置,因为 GETVAL 不使用它  
        int x = semctl(semid, i, GETVAL);  

        printf("Semaphore %d, value %d\n", i, x); 

            // =================================== end ===============================

        }

更完整、更严谨的答案:
(记得还要在顶部导入包:#include <stdlib.h>   //以使用exit函数)

for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
    {
        // =================================== begin ===============================

        /*请调用semctl函数,读取并输出与上述数组输出相同的输出*/
 
        // 注意:getval_arg.val 在这里不需要设置,因为 GETVAL 不使用它  
        int x = semctl(semid, i, GETVAL);  
        if (x == -1) {  
        printf("GETVAL for semaphore %d failed (%d)\n", i, errno);  
        exit(EXIT_FAILURE);  
    }
        printf("Semaphore %d, value %d\n", i, x); 

            // =================================== end ===============================

        }

五、基于命名管道与信号的进程间通信

(1)第1关:命名管道与信号IPC操作考查

没啥好说的,不会的操作系统考试就靠记呗!!

  • sleep(1); 休眠1秒
  • 打开读通道——> open("FIFO",O_RDONLY);
  • 打开写通道——> open("FIFO",O_WRONLY);
  • 开始写——>write(fd,"heool0penEuler",1);

答案如下:

 if(pid==0)
    {
        // ============================= begin =========================
        /*子进程打开读管道,随后关闭管道*/
        int fd;
        fd = open("FIFO",O_RDONLY);  /*rd->only 写*/
        /*关闭*/
        close(fd);
    }
    else
    {
        
        /*父进程打开写通道,休眠1秒,尝试写入*/
        int fd;
        fd = open("FIFO",O_WRONLY);  /*wr->only 写*/
        int ret;
        sleep(1); /*休眠1秒*/
        /*写入*/
        ret = write(fd,"heool0penEuler",1);

        // ============================= end =========================
    }

六、 Linux vi/vim编辑器(难度:简单)

(注意这类题目在操作之前需要初始化任务环境)

(1)第1关:vi/vim基本用法
(2)第2关:vi/vim工作模式切换
  • wq :保存并退出
  • i:插入
(3)第3关:vi/vim命令模式
  • dd:删除
  • yy:复制
  • p:粘贴
(4)第4关:vi/vim底线命令模式(重点)
  • 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2。 :1,$s/word1/word2/g
  • 将文件第2-5行内容另存为oldFileCpy.txt文件:2,5 w oldFileCpy.txt

七、读文件系统函数(难度:简单)

(1)第1关:读文件系统函数

(此题注意:知道read()函数是啥就行了。其次知道其返回值和其函数的参数)

  • 函数原型:read(int fd, void *buf, size_t count);
  • fd:看上文(读文件的地址)
  • *buf:字符数组缓冲区的位置
  • 最后这个size_t count:就是读到的全部字符的个数——> sizeof(buffer)-1
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define rwmode 0
int main()
{
    int fd;
    char buffer[1024];
    int n;
    fd = open("/data/workspace/myshixun/case1/testFIle", rwmode);
    if (fd < 0)
    {
        printf("Open file error!\n");
        exit(1);
    }
    else
        printf("open testFIle ok!\n");
    //-------------begin----------------------  
    //请使用read函数将其读入buffer中
    n = read(fd,buffer,sizeof(buffer)-1);
    //--------------end----------------------  
    buffer[n] = '\0';
    printf("%s\n", buffer);
    close(fd);
    return 0;
}

八、写文件系统函数(难度:中等)

(1)第1关:写文件系统函数

(这题其实就是一个综合。先用read()读函数,再用write()写函数)

  • 函数原型:ssize_t write(int fd, const void *buf, size_t count);
  • 读的文件的地址题目也给出:int resource_fd

  • char buffer[FILESIZE]:字符数组

  • #define FILESIZE 1024 (该字符数组最大容量,也是题目要求读取的量)
  • 所以:(read(resource_fd,buffer,FILESIZE ))>0,因为读到了就要返回得到的个数。
  • char buffer[FILESIZE], *p; p = buffer; :要写入的字符数组信息地址在p

  • 写的目的文件地址题目也给出了:int  destination_fd

  • 具体要写的字符个数(前面被赋值):readbytes = read(resource_fd,buffer,FILESIZE)

  • 所以:(writebytes = write(destination_fd,p,readbytes))>0,因为写到了就要返回个数

综合解答:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define resource_mode 0
#define destination_mode 0774
#define FILESIZE 1024

int main(int argc, char *argv[])
{
    int resource_fd, destination_fd;
    char buffer[FILESIZE], *p;
    int readbytes, writebytes;
    if (argc != 3)
    {
        printf("Usage:copy from resource file to destination file\n %s src_file dest_file\n", argv[0]);
        exit(0);
    }
    if ((resource_fd = open(argv[1], resource_mode)) == -1)
    {
        perror("Can't open source file");
        exit(0);
    }
    if ((destination_fd = creat(argv[2], destination_mode)) == -1)
    {
        perror("Can't create destination file");
        exit(0);
    }
    // ======================= begin =======================================

    // 请使用read函数读取前1024字节的内容读到缓冲区buffer中
    while ((readbytes = read(resource_fd,buffer,FILESIZE))>0)

    // ========================== end =======================================
    {
        p = buffer;
        if ((readbytes == -1) && (errno != EINTR))
            break;
        else if (readbytes > 0)
        {
            // ======================= begin =======================================

            // 请使用write函数读取到的前1024字节的内容写到目的文件中
            while ((writebytes = write(destination_fd,p,readbytes))>0)

            // ========================== end =======================================
            {
                if ((writebytes == -1) && (errno != EINTR))
                    break;
                else if (writebytes == readbytes)
                    break;
                else if (writebytes > 0)
                {
                    p += writebytes;
                    readbytes -= writebytes;
                }
            }
            if (writebytes == -1)
                break;
        }
    }
    close(resource_fd);
    close(destination_fd);
    return 0;
}

 九、进程基础操作(难度:简单)

(1)第1关:进程基础操作考察

(这一关没啥好说的,难度很简单)

  • 了解fork()函数即可
  • 注意空格的输出(父、子进程都一样):printf("bye! "); 
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
  /*请开始填写*/
  pid_t pid =fork();
  if(pid==0){
    printf("bye! ");
  }
  else if(pid>0){
    printf("bye! ");
  }
      return 0;
}

标签:mutex,函数,int,buffer,fd,实训,printf,模拟考试,os
From: https://blog.csdn.net/m0_74363339/article/details/140064838

相关文章

  • 【Docker Compose】掌握容器资源管理:高效限制CPU与内存使用
    【DockerCompose】掌握容器资源管理:高效限制CPU与内存使用一、DockerCompose介绍1.1DockerCompose简介1.2DockerComposeV2简介1.3DockerComposeV1与V2版本区别1.4docker-compose.yaml部署文件介绍二、检查本地docker环境2.1本地环境规划2.2......
  • 一加12搞机(kernelsu+lsposed)
    刷机温馨提示:如果你不知道root的意义在哪,建议不要解锁和root,到时候救砖或者回锁都挺麻烦。刷全量包最新版的系统没有更新推送,所以去一加社区[0]找了个全量包来刷,。安装方式可以看帖子里的内容,说的比较详细,这里截图一部分:解锁bootloader在系统与更新-》开发者选项里勾选OEM......
  • Centos7.9安装普罗米修斯+grafana
    一、基本概念​1、之间的关系​prometheus与grafana之间是相辅相成的关系。作为完美的分布式监控系统的Prometheus,就想布加迪威龙一样示例和动力强劲。在猛的车也少不了仪表盘来观察。于是优雅的可视化平台Grafana出现了。​简而言之Grafana作为可视化......
  • Python教程:开箱即用的Python os模块知识
    1.简介注:文末有福利领取哦Python的os模块提供了许多接口用于与操作系统进行交互,包括文件操作、目录操作、路径操作、环境变量操作、系统信息获取等。以下是os模块中常用的接口及其解释:文件和目录操作:os.remove(path):删除指定路径的文件。os.rename(src,dst):......
  • [本科项目实训] netstat 端口检测
    问题描述多人访问服务器启动程序实例时可能产生端口占用的程序出错,可以使用netstat进行端口检测。解决方案第一步,下载netstat:aptinstallnet-tools第二步,使用netstat查询占用对应端口号的进程:netstat-anlpt|grepyour_port执行结果如下例:root@xxxx:~$netstat-anlp......
  • [本科项目实训] P-Tuning v2 训练数据生成
    思路由于我们项目的任务并不属于通用的自然语言处理任务,所以显然没有公开数据集,因而手工生成与模型生成相结合的方式或许是一个不错的选择。在不同的使用方式和任务情景下,我们曾经尝试了不同的数据集生成方式:#v1importjsonimportrandomtrain_f=True#train_f=False......
  • [本科项目实训] P-Tuning v2 测试记录
    测试脚本PRE_SEQ_LEN=64CHECKPOINT=dsbtpg-chatglm-6b-pt-64-2e-2STEP=500CUDA_VISIBLE_DEVICES=0python3main.py\--do_predict\--validation_filedevVX.json\--test_filedevVX.json\--overwrite_cache\--prompt_columncontent\......
  • [本科项目实训] P-Tuning v2 训练记录
    训练脚本PRE_SEQ_LEN=64LR=2e-2CUDA_VISIBLE_DEVICES=0python3main.py\--do_train\--train_filetrainVX.json\--validation_filedevVX.json\--prompt_columncontent\--response_columnsummary\--overwrite_cache\--mo......
  • [本科项目实训] 模型量化技术
    概述模型量化作为一种能够有效减少模型大小,加速深度学习推理的优化技术,主要包含8/4/2/1bit等精度设置。在8-bit低精度推理中,我们将一个原本FP32的weight/activation浮点数张量转化成一个int8/uint8张量,从而减少内存带宽和存储空间,并提高系统吞吐量降低系统时延。[2]......
  • [本科项目实训] Hugging Face Transformers 模型部署与微调
    TransformersHuggingFaceTransformer提供了模型的加载、推理、微调接口,使用该库可以轻松完成自然语言模型的部署微调工作,其有继承自AutoClass的四个最为常见的接口,且调用方式均为AutoClass.from_pretrain("model_name"):AutoTokenizer:用于文本分词AutoFeatureExtractor:用......