实验3-文件誊抄实验

编程实现多进程并发实现文件誊抄(源码下载)

  利用多个共享内存(有限空间)构成的环形缓冲,将源文件复制到目标文件,实现两个进程的誊抄。

1、首先我们先了解一下后续会用到的execl函数

  (1)exec函数特点:

  当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。用另一个新程序替换了当前进程的正文、数据、堆和栈段。当前进程的正文都被替换了,那么execl后的语句,即便execl退出了,都不会被执行。

  (2)execl函数:

  Linux下头文件:#include <unistd.h>

  函数定义:int execl(const char *path, const char *arg, ...);

  函数说明:execl()其中后缀"l"代表list也就是参数列表的意思,第一参数path字符指针所指向要执行的文件路径, 接下来的参数代表执行该文件时传递的参数列表:argv[0],argv[1]... 最后一个参数须用空指针NULL作结束。

  函数返回值:成功则不返回值, 失败返回-1, 失败原因存于errno中,可通过perror()打印

  下面是execl函数使用的样例:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <string.h>
 7 #include <sys/wait.h>
 8 /**
 9  * execl.c函数实现
10  *
11  */
12 int main(int argc, char* argv[])
13 {
14     pid_t pid = fork();
15     if(pid == -1)
16     {
17         perror("fork error");
18         exit(1);
19     }
20
21     // 子进程执行程序
22     if(pid == 0)
23     {
24         execl("/home/caoyang/桌面/test_OS/exec/hello", argv[1],NULL);
25         perror("execl");
26         exit(1);
27     }
28
29     wait(&pid);
30     return 0;
31 }

  execl.c中执行的另一个程序:

 1 #include<stdio.h>
 2 int main(int argc,char *argv[])
 3 {
 4     int i;
 5     printf("hello world\n");
 6     printf("argc:%d\n",argc);
 7     for(i=0;i<argc;i++)
 8     {
 9         printf("parameter %d is:%s\n",i,argv[i]);
10     }
11     return 0;
12 }

  在终端下输入./a.out h1 h2 ;运行结果在终端下显示应该是:

1 hello world
2 argc:1
3 parameter 0 is h1

2、了解一下共享缓冲区的概念

  共享存储区 :共享存储区是UNIX系统中通信速度最高的一种通信机制。该机制可使若干进程共享主存中的某一个区域,且使该区域出现(映射)在多个进程的虚地址空间中。

  

  共享存储区机制只为进程提供了用于实现通信的共享存储区和对共享存储区进行操作的手段,当用户需要使用该机制时,必须自己设置同步和互斥措施才能保证实现正确的通信。

3、Linux下面共享内存接口

  (1)创建、获得一个共享存储区shmget  

  头文件:#include<sys/types.h>、#include<sys/ipc.h>、#include<sys/shm.h>

  函数定义:int shmget(key,size,flag);
  函数参数说明:key_t key; //key是共享存储区的名字;int size, //size是其大小(以字节计);int flag;//flag是用户设置的标志,如IPC_CREAT|0666。IPC_CREAT表示若系统中尚无指名的共享存储区,则由核心建立一个共享存储区;若系统中已有共享存储区,便忽略IPC_CREAT
  (2)共享存储区的附接shmat:从逻辑上将一个共享存储区附接到进程的虚拟地址空间上。

  系统调用格式:virtaddr=shmat(shmid,addr,flag)

  参数定义:char *shmat(shmid,addr,flag);int shmid,flag;char * addr; /*一般使用NULL*/其中,shmid是共享存储区的标识符;addr是用户给定的,将共享存储区附接到进程的虚地址空间;flag为0时,表示可读、可写;返回值是共享存储区所附接到的进程虚地址viraddr

4、代码实现

  (1)初始化工作:

 1 pid_t p[2];
 2 //创建信号灯
 3 int semid;
 4 semid = semget(semKey, 2, IPC_CREAT|0666);
 5
 6 //创建共享缓冲区
 7 int shmid;
 8 shmid = shmget(shmKey, sizeof(shareBuf), IPC_CREAT|0666);
 9 shareBuf *sBuf = (shareBuf *)shmat(shmid, NULL, 0);
10 sBuf->over = 0; //初始状况下降拷贝文件结束标志设置为0 当get进程中文件读取结束的时候sBuf->over设置为1

  (2)使用execl函数,子进程分别执行读写进程,读文件、写文件名分别在main函数命令行参数第一个和第二个位置

 1 if((p[0] = fork()) == 0) {
 2     execl("/home/caoyang/桌面/OS实验/文件誊抄实验/get", argv[1],NULL);
 3     perror("execl error......\n");
 4     exit(1);
 5 }
 6 if((p[1] = fork()) == 0) {
 7     execl("/home/caoyang/桌面/OS实验/文件誊抄实验/put", argv[2],NULL);
 8     perror("execl error......\n");
 9     exit(1);
10 }

  (3)get.c中除了初始化本身进程的信号灯和得到共享缓冲区之外,主要做的就是读取文件:

while(sBuf->over != 1) {
        //执行P操作
        P(semid, 0);
        size = fread(sBuf->data[readNum], sizeof(char), 80, fp); //读取文件内容
        sBuf->length[readNum] = size;

        if(size < 80) {
            printf("------reading process have get a blocking......+current_read_size:%d\n",count*80+size);
            sBuf->over = 1; //当最后读取内容小于80的时候结束
        } else {
count ++;
            printf("------reading process have get a blocking......+current_read_size:%d\n",count*80);
            readNum = (readNum + 1) % 10;
        }
        //执行V操作
        V(semid, 1);
        sleep(0.1);
    }

  (4)put.c同get.c,做写文件操作:

while(1) {
        P(semid, 1);
        if(sBuf->over == 1) {
            //fwrite(sBuf->data[writeNum], sizeof(char), 80, fp);
            V(semid, 0);
            break;
        }
        //不关闭流的情况下,每次读或写数据后,文件指针都会指向下一个待写或者读数据位置的指针
        fwrite(sBuf->data[writeNum], sizeof(char), 80, fp);

        count ++;
        printf("++++++writeing process have get a blocking......+current_write_size:%d\n",count*80);

        writeNum = (writeNum + 1) % 10;
        V(semid, 0);
    }

  (5)另附上本次实验作为共享缓冲区结构体:

typedef struct sharedBuf {
    char data[10][80];
    int length[10];
    int over; //结束标志
}shareBuf;

5、实验结果

  (1)验证可执行程序誊抄的正确性:在终端下输入./mian test1 copy,其中test1是在Linux下面自定义一个可执行程序文件名,copy是誊抄之后的文件

  使用Linux下面cmp命令比较两个文件的正确性,发现没有错误,我们在具体查看一下文件大小长度等信息,在终端输入stat copy test1,查看两个文件的具体信息,发现大小相同

  (2)验证文本文件誊抄的正确性:在终端下输入./mian source.txt copy.txt,其中source.txt是在Linux下面创建的一个文本文件,copy.txt是誊抄之后的文件

  使用Linux下面cmp命令比较两个文件的正确性,发现没有错误,我们在具体查看一下文件大小长度等信息,在终端输入stat copy.txt source.txt,查看两个文件的具体信息,发现大小相同

原文地址:https://www.cnblogs.com/fsmly/p/10107712.html

时间: 2024-10-11 23:21:39

实验3-文件誊抄实验的相关文章

密码学实验之文件加密

文件加解密实验 [实验内容] 利用DES.AES.RC2算法对文本.图片.音频.视频等文件进行加解密运算 文件加解密实验 [实验原理] 计算机中一些不适合公开的隐私或机密文件很容易被黑客窃取并非法利用解决这个问题的根本办法就是对重要文件进行加密.实际应用中多直接使用系统自带工具或其它专用工具进行文件加解密工具均采用各种加解密算法对文件进行保护. 本实验中通过DES.AES.RC4算法对文本.图片.音频.视频等文件的内容进行加解密运算.加密的大致过程为读取文件内容.加密.将密文写入文件进行内容覆盖

磁盘和文件系统管理的实验

磁盘和文件系统管理的实验 在此实验里,需要开启一台Linux虚拟机,在这里我开启的是rh-2.在正式开始实验之前,我们先开启2个硬盘 按照如上方法,再添加1个硬盘.下图就是创建的所有硬盘: 基本磁盘管理:四个重要步骤:分区,格式化,挂载,自动挂载第一步:分区 注:[fdisk –l]命令查看硬盘信息添加新硬盘后,必须重启: 注:[init 6]为重启的命令重启之后,再输入[fdisk –l]命令,则所有添加的硬盘都有了: 接下来对每一个硬盘进行分区:首先是对sdb进行分区: 从上图可以看出来,s

Mysql 8.0 导入txt文件操作(课程实验)

一.实验准备: 1.实验设备:Dell laptop 7559; 2.实验环境:windows 10操作系统; 3.数据库版本:mysql 8.0; 二.实验目的: 1.将一个宠物表pet.txt文件导入数据库; 2.掌握使用查看和修改mysql文件操作的全局变量 三.实验步骤: 1.用cmd登录root权限的sql服务器(由于mysql8.0在Windows10上,安全权限问题,普通用户权限无法成功导入文件或进行文件操作.反复查询了各大技术网站也未能成功实现.) 所以命令如下:   以上结果即

操作系统(实验二、作业调度模拟程序实验)

实验二.作业调度模拟程序实验 专业 商业软件工程   姓名 丘惠敏 学号 201406114203 一.        实验目的   (1)加深对作业调度算法的理解: (2)进行程序设计的训练. 二.        实验内容和要求 用高级语言编写一个或多个作业调度的模拟程序. 单道批处理系统的作业调度程序.作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所运行的时间等因素. 三.        实验方法.步骤及结果测试   1.   

实验二、作业调度模拟实验

13物联网  201306104112 徐剑锋 一. 实验目的 (1)加深对作业调度算法的理解: (2)进行程序设计的训练. 二. 实验内容和要求 用高级语言编写一个或多个作业调度的模拟程序. 单道批处理系统的作业调度程序.作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所运行的时间等因素. 作业调度算法: 1) 采用先来先服务(FCFS)调度算法,即按作业到达的先后次序进行调度.总是首先调度在系统中等待时间最长的作业. 2) 短作业

实验一——缓冲区溢出漏洞实验

Linux实验一 —— 缓冲区溢出漏洞实验 20122137 一.实验描述 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写. 二.实验准备 系统用户名shiyanlou,密码shiyanlou 实验楼提供的是64位Ubuntu linux,而本次实验为了方便观察汇编语句,我们需要在32位环境下作操作,因此实验之前需要做一些准备. 1.

实验二、作业调度模拟程序实验

专业 :物联网工程  姓名: 梁晓旋 学号 :201306104136 一. 实验目的 (1)加深对作业调度算法的理解: (2)进行程序设计的训练. 二. 实验内容和要求 用高级语言编写一个或多个作业调度的模拟程序. 单道批处理系统的作业调度程序.作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所运行的时间等因素. 作业调度算法: 1) 采用先来先服务(FCFS)调度算法,即按作业到达的先后次序进行调度.总是首先调度在系统中等待时间最

实验三、动态优先数实验

一.  实验目的      用高级语言完成一个进程调度程序,以加深对进程的概念及进程调度算法的理解. 二.  实验内容和要求 编写并调试一个模拟的进程调度程序,采用“最高优先数优先”调度算法对N(N不小于5)个进程进行调度.“最高优先级优先”调度算法的基本思想是把CPU分配给就绪队列中优先数最高的进程. #include"stdio.h" #include"stdlib.h" #include"string.h" typedef struct n

实验二、作业调度模拟程序实验 (已修改格式)

实验二.作业调度模拟程序实验 专业:计算机科学与技术网络工程   姓名:陈玉婷  学号201306114132 一.实验目的 (1)加深对作业调度算法的理解: (2)进行程序设计的训练. 二.实验内容和要求 用高级语言编写一个或多个作业调度的模拟程序. 作业调度算法:1)采用先来先服务(FCFS)调度算法,即按作业到达的先后次序进行调度.总是首先调度在系统中等待时间最长的作业.2)短作业优先 (SJF) 调度算法,优先调度要求运行时间最短的作业.3)响应比高者优先(HRRN)调度算法,为每个作业