您的当前位置:首页正文

杭电(杭州电子科技大学)操作系统实验三:Linux进程管理

2024-11-21 来源:个人技术集锦

前言

实验内容

(1)实现一个模拟的shell
(2)实现一个管道通信程序
(3)利用Linux的消息队列通信机制实现两个线程间的通信
(4)利用Linux的共享内存通信机制实现两个进程间的通信

实验一

可能问到的问题:
①execl()函数的参数以及其实现的原理
②fork()函数

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

#define MAX_CMD_LEN 20 //输入命令最大长度
#define CMD_COLLECTION_LEN 4 //命令数组长度

#define INVALID_COMMAND -1 //未识别命令
#define EXIT 0 //正常退出
#define CMD_1 1
#define CMD_2 2
#define CMD_3 3

#define TRUE 1

char *cmdStr [CMD_COLLECTION_LEN] = {"exit","cmd1","cmd2","cmd3"};
//命令数组

int getCmdIndex(char *cmd)
{//判断输入命令是否合法
    int i;
    for(i=0;i<CMD_COLLECTION_LEN;i++)
    {
        if(strcmp(cmd,cmdStr[i])==0)
        {
            return i;
        }
    }
    return -1;
}

void myFork(int cmdIndex)
{
    pid_t pid;//pid_t 实际上是int型
    if((pid = fork())<0)//fork 子进程是父进程的副本 
    {//fork返回-1说明创建失败,打印fork error
        printf("fork error");
        exit(0);//退出程序
    }
    else if(pid == 0)//fork返回0说明当前运行的是子进程,所以可以进行替换
    {	
        int execl_status = -1;//接受execl函数的返回值
        printf("child is running");
        switch(cmdIndex)
        {
            case CMD_1:
                execl_status = execl("./cmd1","cmd1",NULL);
				//执行程序路径,参数名,最后一个参数须用空指针NULL作结束
                break;
            case CMD_2:
                execl_status = execl("./cmd2","cmd2",NULL);
                break;
            case CMD_3:
                execl_status = execl("./cmd3","cmd3",NULL);
                break;
            default:
                printf("Invalid Command\n");
                break;
        }
        if(execl_status<0)//程序替换失败,即运行失败
        {
            printf("fork error");
            exit(0);
        }
        printf("fork success\n");
        exit(0);
    }
    else
    {
        return;
    }
}
void runCMD(int cmdIndex)
{
    switch(cmdIndex)
    {
        case INVALID_COMMAND://未识别命令
            printf("COMMAND NOT FOUND \n");
            break;
        case EXIT://退出命令
            exit(0);
            break;
        default:
            myFork(cmdIndex);
            break;
    }
}
int main()
{
    pid_t pid;//进程号 
    char cmdStr[MAX_CMD_LEN];
    int cmdIndex;
    while(TRUE)
    {
        printf("\n---Input your command > ");
        scanf("%s",cmdStr);
        cmdIndex = getCmdIndex(cmdStr);//判断合法性命令
        runCMD(cmdIndex);//给出对应反应
        wait(NULL); //父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出
        //参数是NULL说明我们不在意子进程是如何结束的 存在一套宏专门用来记录进程结束状态(是否正常退出等)
		printf("waiting for next command");
    }
}

实验二

#include "fcntl.h"
#include "semaphore.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/ipc.h"
#include "sys/sem.h"
#include "sys/types.h"
#include "sys/wait.h"
#include "unistd.h"
#define BUF_MAX_SIZE 8192

// 如果x为假,则报错
void CHECK(int x){
	if(!x){
		printf("error appear");
		exit(-1);
	}	
}
int main(int argc, char **argv) {
    int pipefd[2], pid, i = 0;
    int flag = 0;
    char buf[BUF_MAX_SIZE];//管道缓冲池
    char str[BUF_MAX_SIZE];

    sem_t *write_mutex;//sem_t本质上是一个长整形 对于管道进行写操作的互斥信号量
    sem_t *read_mutex1;//进程二三都发完消息的信号量
    sem_t *read_mutex2;
    write_mutex = sem_open("pipe_test_wm", O_CREAT | O_RDWR, 0666, 0);
    read_mutex1 = sem_open("pipe_test_rm_1", O_CREAT | O_RDWR, 0666, 0);
    read_mutex2 = sem_open("pipe_test_rm_2", O_CREAT | O_RDWR, 0666, 0);
	/*
		创建有名信号量,默认值都为0
		sem_t *sem_open(const char *na
显示全文