OS实验2的代码和readme

这篇博客探讨了进程间的软中断通信,包括信号处理和同步问题,以及进程间如何通过管道进行数据交换。此外,文章详细介绍了内存分配的三种算法:首次适应、最优适应和最差适应,并通过代码实现展示了内存分配和回收的过程。实验结果显示了不同算法的执行效果和潜在问题。
摘要由CSDN通过智能技术生成

目录

OS第二次实验readme

一、进程的软中断通信

二、进程的管道通信

三、内存分配算法


代码1:

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

int wait_flag = 0; //用来控制子进程与父进程同步的变量
void stop(int signum);
int pid1, pid2;
main()
{
    signal(14, stop); //此处可以修改为2、3、14
    while ((pid1 = fork()) == -1)
        ;
    if (pid1 > 0)
    {
        while ((pid2 = fork()) == -1)
            ;
        if (pid2 > 0)
        {
            //signal(2,stop);
            alarm(2);       //若不是用14号中断请注释掉这里,这是用来发送14号中断的闹钟函数
            sleep(2);       //等待中断到来
            kill(pid1, 16); //向子进程1发送16号中断
            kill(pid2, 17); //向子进程2发送17号中断
            wait(0);        //等待两个子进程结束
            wait(0);
            printf("\n Parent process is killed! \n");
            exit(0);
        }
        else
        {
            wait_flag = 0;    //在收到17号中断之前,这个变量会一直令子进程进入空转
            signal(17, stop); //接受17号中断
            while (!wait_flag)
            {
            }
            printf("\n Child process 2 is killed by the parent! \n");
            exit(0);
        }
    }
    else
    {
        wait_flag = 0;    //在收到16号中断之前,这个变量会一直令子进程进入空转
        signal(16, stop); //接受6号中断
        while (!wait_flag)
        {
        }
        printf("\n Child process 1 is killed by the parent! \n");
        exit(0);
    }
}

void stop(int signum)
{
    if (signum != 2) //只有当收到父进程发来的中断时才能改变状态,这里请与第13行的信号量保持一致
        wait_flag = 1;
    //printf("\n  stop test  pid1:%d    pid2:%d    signal:%d\n",pid1,pid2,signum);
    printf("\n %d stop test \n", signum);
}

代码2:

有互斥锁的:

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

int pid1, pid2;
main()
{
    int fd[2];
    char InPipe[1000];
    //char c1 = '1', c2 = '2';
    char *w1=(char*)"1",*w2=(char*)"2";
    pipe(fd);
    while ((pid1 = fork()) == -1)
        ;
    if (pid1 == 0)
    {
        //printf("\n first process start \n");
        lockf(fd[1], 1, 0);//补充,锁定管道
         //补充,分200次向管道写入1
        for(int i=0;i<200;i++)
        write(fd[1],w1,1);
        sleep(3);
        lockf(fd[1], 0, 0);//补充,解除锁定
        exit(0);
    }
    else
    {
        while ((pid2 = fork()) == -1)
            ;
        if (pid2 == 0)
        {
           //printf("\n second process start \n");
          lockf(fd[1], 1, 0);
            //补充,分200次向管道写入2
            for(int i=0;i<200;i++)
            write(fd[1],w2,1);
            sleep(3);
            lockf(fd[1], 0, 0);
            exit(0);
        }
        else
        {
            wait(0);
            wait(0);
            //printf("\n parent process start \n");
            //补充,从管道中读出400个字符
            read(fd[0],InPipe,400);
            //加入字符串结束符
            InPipe[400]='\0';
            printf("%s\n", InPipe);
            exit(0);
        }
    }
}

没有互斥锁的:

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

int pid1, pid2;
main()
{
    int fd[2];
    char InPipe[1000];
    //char c1 = '1', c2 = '2';
    char *w1=(char*)"1",*w2=(char*)"2";
    pipe(fd);
    while ((pid1 = fork()) == -1)
        ;
    if (pid1 == 0)
    {
        //printf("\n first process start \n");
        //lockf(fd[1], 1, 0);//补充,锁定管道
         //补充,分200次向管道写入1
          for(int i=0;i<20;i++)
           {
                write(fd[1],w1,1);
                sleep(0.1);
           }
       // lockf(fd[1], 0, 0);//补充,解除锁定
        exit(0);
    }
    else
    {
        while ((pid2 = fork()) == -1)
            ;
        if (pid2 == 0)
        {
           //printf("\n second process start \n");
           //lockf(fd[1], 1, 0);
            //补充,分200次向管道写入2
            for(int i=0;i<20;i++)
           {
                write(fd[1],w2,1);
                sleep(0.1);
           }
            //lockf(fd[1], 0, 0);
            exit(0);
        }
        else
        {
            wait(0);
            wait(0);
            //printf("\n parent process start \n");
            //补充,从管道中读出400个字符
            read(fd[0],InPipe,400);
            //加入字符串结束符
            InPipe[400]='\0';
            printf("%s\n", InPipe);
            exit(0);
        }
    }
}

代码3:

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

#define PROCESS_NAME_LEN 32   //进程名长度
#define MIN_SLICE 10          //最小碎片的大小
#define DEFAULT_MEM_SIZE 1024 //默认内存终止位置
#define DEFAULT_MEM_START 0   //默认内存起始位置
#define LEAST_DELTA 10        //最小的内部碎片大小
//内存分配算法
#define MA_FF 1
#define MA_BF 2
#define MA_WF 3

int pid = 0;
int mem_size = DEFAULT_MEM_SIZE;
int flag = 0;         //设置内存总大小之后,不可再次更改
int ma_algorithm = 1; //用来标记排序算法

//函数声明
struct free_block_type *init_free_block(int mem_size); //初始化空闲块链表
void display_menu();                                   //展示程序功能
int set_mem_size();                                    //设置内存大小
void set_algorithm();                                  //设置算法
void rearrange(int algorithm);                         //根据相应相应算法给空闲链表排序
void rearrange_FF();                                   //首次适应
void rearrange_BF();                                   //最优适应
void rearrange_WF();                                   //最差适应
int new_process();                                     //初始化一个新进程
int allocate_mem(struct allocated_block *ab);          //给一个新进程分配内存空间
void compact_mem();                                    //内存紧缩
void kill_process();                                   //删除一个进程
struct allocated_block *find_process(int pid);         //根据pid遍历找到一个进程
int free_mem(struct allocated_block *ab);              //释放内存空间
int dispose(struct allocated_block *free_ab);          //更新占用内存列表
int display_mem_usage();                               //展示已占用内存部分
void do_exit();                                        //退出程序
//函数声明

//存储空闲孔的数据结构,采用链表
struct free_block_type
{
    int size;
    int start_addr;
    struct free_block_type *next;
    struct free_block_type *parent;
};
//指向内存中空闲块链表的首指针
struct free_block_type *free_block;

//存储每个进程分配到的内存块的数据结构,采用链表
struct allocated_block
{
    int pid;
    int size;
    int start_addr;
    char process_name[PROCESS_NAME_LEN];
    struct allocated_block *next;
    struct allocated_block *parent;
};
//进程分配内存块链表的首指针
struct allocated_block *allocated_block_head = NULL;

main()
{
    //system("chcp 65001");
    char choice;
    pid = 0;
    int mem_size = DEFAULT_MEM_SIZE;
    free_block = init_free_block(mem_size); //初始化一个空闲链表
    while (1)
    {
        display_menu();      //显示菜单
        setbuf(stdin, NULL); //刷新输入缓冲区
        // fflush(stdin); //unavailable in linux
        choice = getchar(); //获取用户输入
        getchar();
        switch (choice)
        {
        case '1':
            set_mem_size(); //设置内存大小
            break;
        case '2':
            set_algorithm(); //设置算法
            flag = 1;
            break;
        case '3':
            new_process(); //创建新进程
            flag = 1;
            break;
        case '4':
            kill_process(); //删除进程
            flag = 1;
            break;
        case '5':
            display_mem_usage(); //显示内存使用情况
            flag = 1;
            break;
        case '0':
            do_exit();
        }
    }
}
//初始化空闲块,默认为一块,可以指定大小及起始地址
struct free_block_type *init_free_block(int mem_size)
{
    struct free_block_type *fb;
    fb = (struct free_block_type *)malloc(sizeof(struct free_block_type));
    if (fb == NULL)
    {
        printf("No mem\n");
        return NULL;
    }
    fb->size = mem_size;
    fb->start_addr = DEFAULT_MEM_START;
    fb->next = NULL;
    fb->parent = NULL;
    return fb;
}
//显示菜单
void display_menu()
{
    printf("\n");
    printf("1-Set memory size (default=%d)\n", DEFAULT_MEM_SIZE);
    printf("2-Select memory allocation algorithm\n");
    printf("3-New process\n");
    printf("4-Terminate a process\n");
    printf("5-Dispaly memory usage\n");
    printf("0-Exit\n");
}
//设置内存的大小
int set_mem_size()
{
    int size;
    if (flag != 0)
    {
        printf("Cannot set memory size again\n");
        return 0;
    }
    printf("Total memory size=");
    scanf("%d", &size);
    if (size > 0)
    {
        mem_size = size;
        free_block->size = mem_size;
    }
    flag = 1;
    return 1;
}
//设置当前的分配算法
void set_algorithm()
{
    int algorithm;
    printf("\t1-First Fit\n");
    printf("\t2-Best Fit\n");
    printf("\t3-Worst Fit\n");
    scanf("%d", &algorithm);
    if (algorithm >= 1 && algorithm <= 3)
        ma_algorithm = algorithm;
    //按指定算法重新排列空闲区链表
    rearrange(ma_algorithm);
}
//按指定算法重新排列空闲区链表
void rearrange(int algorithm)
{
    switch (algorithm)
    {
    case MA_FF:
        rearrange_FF();
        break;
    case MA_BF:
        rearrange_BF();
        break;
    case MA_WF:
        rearrange_WF();
        break;
    }
}
//首次适应算法
//算法思想:把空闲的孔按照地址顺序进行冒泡排序,并且合并相邻的孔
void rearrange_FF()
{
    struct free_block_type *p0, *p1;
    p0 = p1 = NULL;
    if (free_block != NULL)
        p0 = free_block;
    int num = 0;
    //计算目前空闲孔个数
    while (p0 != NULL)
    {
        num++;
        p0 = p0->next;
    }
    if (num >= 2)
    {
        //若孔数大于等于2,依照地址由小到大排序
        for (int i = 0; i < num - 1; i++)
        {
            p0 = free_block;
            p1 = p0->next;
            for (int j = 0; j < num - 1; j++)
            {
                if (p0->start_addr > p1->start_addr)
                {
                    struct free_block_type *p0p;
                    p0p = p0->parent;
                    p0->next = p1->next;
                    if (p1->next != NULL)
                        p1->next->parent = p0;
                    p1->next = p0;
                    p0->parent = p1;
                    p1->parent = p0p;
                    if (p0p != NULL)
                        p0p->next = p1;
                    p1 = p0->next;
                    if (p0 == free_block)
                    {
                        free_block = p0->parent;
                    }
                }
                else
                {
                    p0 = p1;
                    p1 = p1->next;
                }
            }
        }
        //合并地址相邻孔
        if (free_block != NULL)
        {
            p0 = free_block;
            p1 = p0->next;
            for (int i = 0; i < num - 1 && p0 != NULL && p1 != NULL; i++)
            {
                if (p0->start_addr + p0->size == p1->start_addr)
                {
                    p0->size = p0->size + p1->size;
                    p0->next = p1->next;
                    if (p1->next != NULL)
                        p1->next->parent = p0;
                    free(p1);

                    p1 = p0->next;
                }
                else
                {
                    p0 = p1;
                    p1 = p1->next;
                }
            }
        }
    }
}
//最优适应算法
//算法思想:按照孔的大小由小到大排序,取最小且满足要求者作为分配的孔

void rearrange_BF()
{
    struct free_block_type *p0, *p1;
    p0 = free_block;
    int num = 0;
    //计算目前空闲孔个数
    while (p0 != NULL)
    {
        num++;
        p0 = p0->next;
    }
    if (num >= 2)
    {
        //若孔数大于等于2,依照空的大小由小到大排序
        for (int i = 0; i < num - 1; i++)
        {
            p0 = free_block;
            p1 = p0->next;
            for (int j = 0; j < num - 1; j++)
            {
                if (p0->size > p1->size)
                {
                    struct free_block_type *p0p;
                    p0p = p0->parent;
                    p0->next = p1->next;
                    if (p1->next != NULL)
                        p1->next->parent = p0;
                    p1->next = p0;
                    p0->parent = p1;
                    p1->parent = p0p;
                    if (p0p != NULL)
                        p0p->next = p1;
                    p1 = p0->next;
                    if (p0 == free_block)
                    {
                        free_block = p0->parent;
                    }
                }
                else
                {
                    p0 = p1;
                    p1 = p1->next;
                }
            }
        }
    }
}
//最差适应算法
//算法思想:按照孔的大小由大到小排序,取最大且满足要求者作为分配的孔

void rearrange_WF()
{
    struct free_block_type *p0, *p1;
    p0 = free_block;
    int num = 0;
    //计算目前空闲孔个数
    while (p0 != NULL)
    {
        num++;
        p0 = p0->next;
    }
    if (num >= 2)
    {
        //若孔数大于等于2,依照空的大小由大到小排序
        for (int i = 0; i < num - 1; i++)
        {
            p0 = free_block;
            p1 = p0->next;
            for (int j = 0; j < num - 1; j++)
            {
                if (p0->size < p1->size)
                {
                    struct free_block_type *p0p;
                    p0p = p0->parent;
                    p0->next = p1->next;
                    if (p1->next != NULL)
                        p1->next->parent = p0;
                    p1->next = p0;
                    p0->parent = p1;
                    p1->parent = p0p;
                    if (p0p != NULL)
                        p0p->next = p1;
                    p1 = p0->next;
                    if (p0 == free_block)
                    {
                        free_block = p0->parent;
                    }
                }
                else
                {
                    p0 = p1;
                    p1 = p1->next;
                }
            }
        }
    }
}
//创建新的进程,主要是获取内存的申请数量
int new_process()
{
    struct allocated_block *ab;
    int size;
    int ret;
    ab = (struct allocated_block *)malloc(sizeof(struct allocated_block));
    if (!ab)
        exit(-5);
    ab->parent = NULL;
    ab->next = NULL;
    pid++;
    sprintf(ab->process_name, "PROCESS-%02d", pid);
    ab->pid = pid;
    printf("Memory for %s:", ab->process_name);
    scanf("%d", &size);
    if (size > 0)
        ab->size = size;
    ret = allocate_mem(ab);
    //从空闲区分配内存,ret==1表示分配ok
    if ((ret == 1) && (allocated_block_head == NULL))
    //如果此时allocated_block_head尚未赋值,则赋值
    {
        allocated_block_head = ab;
        return 1;
    }
    else if (ret == 1) //分配成功,将该已分配块的描述插入已分配链表
    {
        ab->next = allocated_block_head;
        allocated_block_head->parent = ab;
        allocated_block_head = ab;
        return 2;
    }
    else if (ret == -1) //分配不成功
    {
        printf("Allocation fail\n");
        free(ab);
        ab = NULL;
        return -1;
    }
    return 3;
}
//分配内存模块,分配成功则返回1,否则返回-1
int allocate_mem(struct allocated_block *ab)
{
    struct free_block_type *p0, *p1;
    int request_size = ab->size;
    p0 = p1 = free_block;

    while (p1 != NULL)
    {
        if (p1->size >= request_size)
        {
            //找到可满足空闲分区且分配后剩余空间足够大,则分割
            if (p1->size - request_size >= LEAST_DELTA)
            {
                ab->start_addr = p1->start_addr;
                p1->size = p1->size - request_size;
                p1->start_addr = p1->start_addr + request_size;
                //在成功分配内存后,应保持空闲分区按照相应算法有序
                rearrange(ma_algorithm);
                return 1;
            }
            //找到可满足空闲分区且但分配后剩余空间比较小,则一起分配
            else
            {
                ab->start_addr = p1->start_addr;
                p0->next = p1->next;
                if (p1->next != NULL)
                    p1->next->parent = p0;
                free(p1);
                if (p1 == free_block)
                    free_block = NULL;
                p1 = NULL;
                //在成功分配内存后,应保持空闲分区按照相应算法有序
                rearrange(ma_algorithm);
                return 1;
            }
        }
        else
        {
            p0 = p1;
            p1 = p1->next;
        }
    }
    //找不可满足需要的空闲分区但空闲分区之和能满足需要,则采用内存紧缩技术,
    //进行空闲分区的合并,然后再分配
    compact_mem();                //内存紧缩
    p0 = p1 = free_block;         //空闲链表头
    if (p1->size >= request_size) //判断
    {
        if (p1->size - request_size >= LEAST_DELTA)
        {
            ab->start_addr = p1->start_addr;
            p1->size = p1->size - request_size;
            p1->start_addr = p1->start_addr + request_size;
            //在成功分配内存后,应保持空闲分区按照相应算法有序
            rearrange(ma_algorithm);
            return 1;
        }
        else
        {
            ab->start_addr = p1->start_addr;
            free(p1);
            if (p1 == free_block)
                free_block = NULL;
            p1 = NULL;
            //在成功分配内存后,应保持空闲分区按照相应算法有序
            rearrange(ma_algorithm);
            return 1;
        }
    }
    else
        return -1;
}
//内存紧缩算法,算法思想:以已分配内存链表遍历,将所有已分配内存向前移动,
//把最后剩下的区域合并为一个大的内存孔
void compact_mem() //内存紧缩
{
    int addr_now = 0; //存放现在的最前端可用地址
    struct allocated_block *ab;
    ab = allocated_block_head; //已分配内存链表头
    while (ab != NULL)         //遍历已分配内存链表,把已占用的部分向前移动
    {
        ab->start_addr = addr_now;      //把当前可用地址赋给ab
        addr_now = addr_now + ab->size; //更新可用地址
        ab = ab->next;                  //继续遍历
    }
    struct free_block_type *fbt, *p;
    //这里是删掉了原来的空闲空间链表,但是因为极端情况可能有问题,我就注释了。不影响运行
    //fbt = free_block;
    //while (fbt != NULL)
    //{
    //p = fbt;
    //fbt = fbt->next;
    //free(p);
    //p = NULL;
    //}

    fbt = (struct free_block_type *)malloc(sizeof(struct free_block_type)); //开辟一个新的指针空间作为空闲链表头
    if (fbt == NULL)
    {
        printf("No mem\n");
    }
    fbt->size = mem_size - addr_now; //计算空闲空间可用地址
    fbt->start_addr = addr_now;      //更新表头信息
    fbt->next = NULL;
    fbt->parent = NULL;
    free_block = fbt;
}
//删除进程,归还分配的存储空间,并删除描述该进程内存分配的节点
void kill_process()
{
    struct allocated_block *ab;
    int pid;
    printf("Kill Process,pid=");
    scanf("%d", &pid);
    ab = find_process(pid);
    if (ab != NULL)
    {
        free_mem(ab);
        dispose(ab);
    }
}
//根据PID遍历找到相应的进程
struct allocated_block *find_process(int pid)
{
    struct allocated_block *pre;
    pre = allocated_block_head;
    while (pre != NULL)
    {
        if (pre->pid == pid)
            return pre;
        pre = pre->next;
    }
    return NULL;
}
//释放进程分配的内存空间
int free_mem(struct allocated_block *ab)
{
    //在空闲链表插入新节点
    int algorithm = ma_algorithm;
    struct free_block_type *fbt, *p0;
    fbt = (struct free_block_type *)malloc(sizeof(struct free_block_type));
    if (!fbt)
        return -1;
    fbt->start_addr = ab->start_addr;
    fbt->size = ab->size;
    fbt->next = NULL;
    p0 = free_block;
    if (free_block == NULL)
    {
        free_block = fbt;
    }
    else
    {
        while (p0->next != NULL)
        {
            p0 = p0->next;
        }
        fbt->parent = p0;
        p0->next = fbt;
    }
    //空闲链表重排
    switch (algorithm)
    {
    case 1:
        rearrange_FF();
        break;
    case 2:
        rearrange_FF();
        rearrange_BF();
        break;
    case 3:
        rearrange_FF();
        rearrange_WF();
        break;
    }
    return 1;
}

int dispose(struct allocated_block *free_ab)
{
    //占用列表更新
    struct allocated_block *ab0, *ab1;
    ab0 = free_ab->parent;
    ab1 = free_ab->next;
    if (ab0 != NULL)
        ab0->next = ab1;
    if (ab1 != NULL)
        ab1->parent = ab0;
    if (free_ab == allocated_block_head)
        allocated_block_head = free_ab->next;
    free(free_ab);
    return 1;
}

int display_mem_usage()
{
    struct free_block_type *fbt = free_block;
    struct allocated_block *ab = allocated_block_head;
    if (fbt == NULL)
    {
        printf("there is no free memory left\n");
    }
    else
    {
        printf("-----------------------------------------------------\n");
        printf("Free Memory:\n");
        printf("%20s %20s\n", "   start_addr", "    size");
        while (fbt != NULL)
        {
            printf("%20d %20d\n", fbt->start_addr, fbt->size);
            fbt = fbt->next;
        }
    }

    printf("\nUsed Memory:\n");
    printf("%10s %30s %10s %10s\n", "PID", "ProcessName", "start_addr", "size");
    while (ab != NULL)
    {
        printf("%10d %30s %10d %10d\n", ab->pid, ab->process_name, ab->start_addr, ab->size);
        ab = ab->next;
    }
    printf("-----------------------------------------------------\n");
    return 0;
}

void do_exit()
{
    exit(0);
}

READ ME:

OS第二次实验readme

一、进程的软中断通信

1.为什么signal函数没效果?

在VSCODE调试模式下signal被禁用,需要以非调试模式运行或者在终端运行。

2.为什么两个子进程还没收到16、17号软中断就输出了?

因为子进程会复制父进程的代码,只有涉及到pid操作的代码不会复制。因此,signal(3,stop)放在创建进程之前,会让三个进程都接受到键盘键入的软中断,从而令子进程输出。

我的办法是在stop函数中,检测signum为16或17时才改变wait_flag的值。

3.ctrl+c,ctrl+d,ctrl+z在linux中意义。

linux下: ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序。 ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程。 ctrl-d 不是发送信号,而是表示一个特殊的二进制值,表示 EOF。 ctrl-\ 发送 SIGQUIT 信号给前台进程组中的所有进程,终止前台进程并生成 core 文件。

实验现象:

1.实验结果:

不按下中断按键,随机顺序输出两个子进程的自定义中断信号后,输出主进程结束标志。

按下中断标志,随机顺序输出两个子进程的中断信号和结束标志,最后输出主进程结束标志。

2.多次运行出现不同结果的原因

由于进程调度和输入软中断时机的不同,运行结果一般会有较大的区别。

由于进程调度的不同,某一时刻可能是两个子进程中的任何一个在运行,输入中断后输出顺序也因此不同。

3.如何修改使得子进程在接收到相应的软中断信号之后才输出结束标志?

在stop函数中,检测signum为16或17时才改变wait_flag的值。wait_flag的值修改之前,两个子进程在空的while循环里等待。

4.修改为闹钟中断

使用alarm函数和signal(14)来控制进程运行

5.使用kill 命令可以在进程的外部杀死进程。进程怎样能主动退出?这两种退出方式哪种更好一些?

调用kill函数时更换第二个参数为其他信号量,再在子进程代码加入exit(0),就可以主动退出。

它们的一个区别是C ++标准库中未指定kill函数.它仅在POSIX中指定. exit是标准C ++.

另一个差异是kill将导致操作系统强制终止进程. exit而是执行清理(通过调用atexit回调和刷新流等)并自愿终止执行.

哪个更好取决于用例,但通常exit更为明智,因为人们通常想要它提供的清理.

二、进程的管道通信

1.lockf函数的用法

lockf()函数允许将文件区域用作信号量(监视锁),或用于控制对锁定进程的访问(强制模式记录锁定)。试图访问已锁定资源的其他进程将返回错误或进 入休眠状态,直到资源解除锁定为止。当关闭文件时,将释放进程的所有锁定,即使进程仍然有打开的文件。当进程终止时,将释放进程保留的所有锁定。

#include <unistd.h>
int lockf(int fd, int cmd, off_t len);

①fd 是打开文件的文件描述符。 为通过此函数调用建立锁定,文件描述符必须使用只写权限(O_WRONLY)或读写权限(O_RDWR)打开。如果调用进程是具有PRIV_LOCKRDONLY 权限的组的成员,它也可以使用lockf()来锁定使用只读权限(O_RDONLY)打开的文件。 ②cmd 是指定要采取的操作的控制值,允许的值在中定义。 如下所示: # define F_ULOCK 0 //解锁 # define F_LOCK 1 //互斥锁定区域 # define F_TLOCK 2 //测试互斥锁定区域 # define F_TEST 3 //测试区域

③len是要锁定或解锁的连续字节数。 要锁定的资源从文件中当前偏移量开始,对于正 len 将向前扩展,对于负 len 则向后扩展(直到但不包括当前偏移量的前面的字节数)。如果 len 为零,则锁定从当前偏移量到文件结尾的区域(即从当前偏移量到现有或任何将来的文件结束标志)。要锁定一个区域,不需要将该区域分配到文件中,因为这样的 锁定可以在文件结束标志之后存在。

在本次实验中,lockf起到互斥锁的作用,避免两个子进程同时向管道中写入数据。

实验现象:

1.程序输出依次200个0和200个1

2.如何实现同步和互斥?

同步:在本次实验中,主进程在创建了两个子进程之后,调用两次wait函数以等待子进程结束。子进程结束时写入自然也已经完成。

互斥:引入互斥锁lockf,当有一个子进程使用管道时,使用lockf函数锁定管道资源,运行结束后解锁。

3.无锁程序的运行结果

1、2字符交替出现,两个子进程交替着向管道中输入。

三、内存分配算法

1.在链表中的加入删去操作,在链头、链尾的操作较为麻烦

修改数据结构为双向链表。(其实还可以首尾相接构成环形链表,操作更简单)

2.display_menu总是执行两遍

应该是缓冲区里每次除了输入数字以外还有一个换行符,这个换行符引发了第二次运行。

清空输入缓冲区或者加一个getchar可以解决问题。

3.给空闲孔排序是用什么算法?

链表的数据结构不太方便用快排。我用了冒泡排序。

首先从头部遍历一遍得到个数,然后根据不同的参数进行冒泡排序。

仅在区块个数大于等于2时运行。

4.空闲孔链表、已占用内存链表的加入删除顺序

空闲链表是先连接到链表末尾,然后依据当前算法进行排序和合并。已占用内存没有必要排序,直接连到链表头尾皆可。

由于在本次实验中是使用特定的数据结构对象来模拟内存分配,并不涉及到真正的内存管理,所以在空闲链表中删去元素时,除非大小刚好对应否则只要修改链表元素值即可而无需增删区块。加入区块、合并区块和内存紧缩也是一样的,只需要对链表元素的地址数值进行修改。

实验现象:

能够基本模拟出内存的排序、分配、回收、合并、压缩等过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值