LINUX系统下多进程的创建与通信前后台进程设计

发布于:2022-12-30 ⋅ 阅读:(312) ⋅ 点赞:(0)

目录
一、课程设计的目的与要求 1
1. 学习 UNIX/LINUX 系统下的多进程创建、控制和通信。 1
二、设计正文 1
1. 任务分析 1
1.1 前台进程应实现的功能如下 1
1.2 后台进程应实现的功能如下: 3
1.3 进程间的协助如图 3 所示: 5
2. 功能实现分析 5
2.1 子进程创建 5
2.2 使用消息队列进行进程间通信 5
2.3 使用命名管道进行进程间通信 6
前台进程读取数据,使用 read 函数,如下 7
后台进程写入数据,使用 write 函数,如下: 7
关闭 FIFO 文件,使用 close 函数,如下: 7
2.4 对输入消息进行处理和转化 8
2.5 执行转化后指令 9
popen 执行结束后,可以通过 fgets 逐行读取执行的结果: 9
三、课程设计总结或结论 10
1. 本次课程设计编写了前台和后台两个进程,并使用了命名管道和消息队列两种进程间通信方式, 实现了 linux 系统上多进程的创建与通信。 10
四、参考文献 10
[1] 宫虎波, Linux 编程从入门到精通. 化学工业出版社, 第一版,2009 年 8 月出版 10
附录 10
4. back.c,其中包含了后台进程的代码 12
一、课程设计的目的与要求

1. 学习 UNIX/LINUX 系统下的多进程创建、控制和通信。
1.1 Linux 上的 bash 和 Windows 中的命令行有很大的不同。但是两者都有完成相似任务的命令,比如 Linux 上 bash 的 ls 命令的功能,类似于 Windows 命令行中的 dir 命令的功能。用 C 语言写一个简单的 Linux 终端软件,接收用户发出的类似于 Windows 命令行中的命令,转换成对应的 Linux 命令加以执行,并将执行的结果回显给用户。比如,用户输入“dir”,进程实际返回“ls”的内容。
1.2 软件包含前、后台两个进程,用户启动前台进程时,前台进程自行启动后台进程。前台进程提供界面,负责接收用户输入,对输入进行转换,并向后台进程发出实际要执行的指令,后台负责执行实际的指令,并将指令执行的结果返回给前台进程,由前台进程在终端显示。本文转载自http://www.biyezuopin.vip/onews.asp?id=15590
二、设计正文
1. 任务分析
1.1 前台进程应实现的功能如下
创建消息队列创建命名管道接受用户输入对输入进行装换
向后台发送实际要执行的指令等待后台返回结果
输出指令执行的的结果
若输入的指令是 exit 则向后台发送 exit 命令删除消息队列
删除命名管道
等待后台进程退出

//
// Created by yutao on 16-10-31.
//

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "msg_operation.h"
#include <wait.h>

void main() {
    int flag = 1;
    int status = -1;
    int msgid, filedsc;
    char buffer[BUFFER_SIZE];
    char *command = NULL;
    struct msg_wrapper data;
    char *stack[100];
    int top, i;
    pid_t fpid;
    fpid = fork();
    if (fpid == 0) {
        execl("./back", "back", "", NULL);
        perror("background");
        exit(errno);
    } else if (fpid < 0) {
        perror("fork");
        exit(errno);
    }
    //创建消息队列
    msgid = msgget((key_t) MESSAGE_ID, 0666 | IPC_CREAT);
    if (-1 == msgid) {
        perror("create message queue");
        exit(errno);
    }
    //创建FIFO并打开
    if (0 != mkfifo(FIFO_NAME, 0777)) {
        perror("fifo");
        exit(errno);
    }

    filedsc = open(FIFO_NAME, O_RDONLY);
    if(-1==filedsc){
        perror("front open FIFO");
        exit(errno);
    }
    while (flag) {
        printf(">>");
        msg_del(&data);
        //读入标准输入
        fgets(buffer, BUFFER_SIZE, stdin);
        //将输入拆分为各个字符串
        top = -1;
        command = strtok(buffer, " \n");
        while (command != NULL) {
            stack[++top] = command;
            command = strtok(NULL, " \n");
        }
        if (top < 0) {
            continue;
        }
        command = stack[0];
        //转化命令
        if (0 == strcmp(command, "dir")) {
            msg_cmd(&data, "ls");
        } else if (0 == strcmp(command, "rename")) {
            msg_cmd(&data, "mv");
        } else if (0 == strcmp(command, "move")) {
            msg_cmd(&data, "mv");
        } else if (0 == strcmp(command, "del")) {
            msg_cmd(&data, "rm");
        } else if (0 == strcmp(command, "touch")) {
            msg_cmd(&data, "touch");
        } else if (0 == strcmp(command, "copy")) {
            msg_cmd(&data, "cp");
        } else if (0 == strcmp(command, "md")) {
            msg_cmd(&data, "mkdir");
        }else if (0 == strcmp(command, "cd")) {
            if (top == 0) {
                msg_cmd(&data, "pwd");
            } else {
                msg_cmd(&data, "cd");
            }
        } else if (0 == strcmp(command, "exit")) {
            flag = 0;
            msg_cmd(&data, "exit");
        } else {
            continue;
        }
        if (flag) {
            //合成指令 
            for (i = 1; i <= top; i++) {
                msg_add(&data, stack[i]);
            }
            msg_end(&data);
        }
        //发送消息
        if (-1 == msgsnd(msgid, (void *) &data, BUFFER_SIZE, 0)) {
            perror("send message");
            exit(errno);
        }
        if (flag) {
        //打开并阻塞读取FIFO数据
            read(filedsc, buffer, BUFFER_SIZE);
            printf("%s", buffer);
        }
    }
    //删除消息队列
    if (msgctl(msgid, IPC_RMID, 0) == -1) {
        perror("delete msg");
        exit(errno);
    }
    //关闭,删除FIFO文件
    if(-1==close(filedsc)){
        perror("front close FIFO");
        exit(errno);
    }
    unlink(FIFO_NAME);
    //等待后台进程退出
    wait(&status);
    //用于显示前后台退出的顺序
    printf("foreground exited\n");
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文含有隐藏内容,请 开通VIP 后查看