V2.0-在记事本功能上添加fork和wait

news2024/11/25 23:12:20

第一篇只是简单使用了open,read,write,lseek实现了基本的记事本功能;

但是当前的系统是linux,应该发挥他的多进程,多线程的作用;

所以,本篇添加创建子进程和父进程等待子进程退出的功能。

有几个注意点:

wait()要与fork()配套出现,如果在使用fork()之前调用wait(),wait()的返回值则为-1,正常情况下wait()的返回值为子进程的PID.

参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就像下面这样:pid = wait(NULL);

如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。

WIFEXITED(status) 这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。

(请注意,虽然名字一样,这里的参数status并不同于wait唯一的参数–指向整数的指针status,而是那个指针所指向的整数,切记不要搞混了。)

 WEXITSTATUS(status) 当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,WEXITSTATUS(status) 就会返回5;如果子进程调用exit(7),WEXITSTATUS(status)就会返回7。请注意,如果进程不是正常退出的,也就是说, WIFEXITED返回0,这个值就毫无意义。

代码:
main.c


#include "./io.h"

struct CMD_input CMD_test1={"creat","copy","display","delete","write"};
struct buffer_param *p;

int main(int argc,char **argv)
{
    //printf("argc :%d,argv[0]:%s,argv[1]:%s,argv[2]:%s\r\n",argc,argv[0],argv[1],argv[2]);
    //agrc指在终端输入的个数
    //argv[0]是第1个参数;
    //argv[1]是第二个参数;,,,,,,
    
    //1-function:解析参数1。判断要做什么操作
    //当前只接解析“creat”,但是预留“cp”,"display","delete"接口
    
    p = ( struct buffer_param *)malloc(sizeof(struct buffer_param));
    memset(p,0,sizeof(struct buffer_param));
    strncpy(p->buffer_param0,argv[0],strlen(argv[0]));
    strncpy(p->buffer_param1,argv[1],strlen(argv[1]));
    strncpy(p->buffer_param2,argv[2],strlen(argv[2]));
    if(argc==4)
    {
        strncpy(p->buffer_param3,argv[3],strlen(argv[3]));
    }
    


    log_test1();//打印所有参数
    read_CMD();//读取指令“creat,write,delete,display,copy”
    task_sch();//执行任务




    return 0;
}





io.c

#include "./io.h"
extern struct buffer_param *p;
extern struct CMD_input CMD_test1;
int flag_of_QUITEDIT=0;
char path_of_file[30];
char flag_of_key_event=0;

void log_test1()
{
    printf("param0:%s\r\n",p->buffer_param0);
    printf("param1:%s\r\n",p->buffer_param1);
    printf("param2:%s\r\n",p->buffer_param2);
    printf("param3:%s\r\n",p->buffer_param3);
}
int read_CMD()
{
    if(strncmp(p->buffer_param1,CMD_test1.CMD_CREAT,strlen(p->buffer_param1))==0)//creat
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"./%s",p->buffer_param2);
        flag_of_key_event = Key_event_creatFile;
        //creat(buffer_param2, S_IRWXU);
    }
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_WRITE,strlen(p->buffer_param1))==0)//write
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"./%s",p->buffer_param2);
        flag_of_key_event = Key_event_writeFile;///写入数据
    }    
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_DISPLAY,strlen(p->buffer_param1))==0)//display
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"cat ./%s",p->buffer_param2);
        flag_of_key_event = Key_event_displayFile;///
    } 
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_CP,strlen(p->buffer_param1))==0)//copy
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"cp ./%s ./%s",p->buffer_param2,p->buffer_param3);
        flag_of_key_event = Key_event_copyFile;///
    } 
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_DELETA,strlen(p->buffer_param1))==0)//display
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"rm ./%s",p->buffer_param2);
        flag_of_key_event = Key_event_deleteFile;///
    } 
    return 0;
}

int task_sch()
{
    int return_of_fork;
    int status_childProcess;//子进程退出状态
    switch(flag_of_key_event)
    {
        case Key_event_creatFile:
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    creat_file();
                else if(return_of_fork>0)
                    wait(NULL);
            break;
        case Key_event_writeFile:
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    write_file();
                else if(return_of_fork>0)
                    wait(&status_childProcess);
                    printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));
            break;
        case Key_event_displayFile:            
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    display_file();
                else if(return_of_fork>0)
                    wait(&status_childProcess);
                    printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));
            break;
        case Key_event_copyFile:
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    copy_file();
                else if(return_of_fork>0)
                    wait(&status_childProcess);
                    printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));

            break;
        case Key_event_deleteFile:
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    delete_file();
                else if(return_of_fork>0)
                    wait(&status_childProcess);
                    printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));
            break;            
        default :break;
    }
}

int creat_file()
{
    int ret=0;
    ret = creat(p->buffer_param2, S_IRWXU);//
    if(ret==-1)
    {
        printf("creat file failed\r\n");
    }
    exit(Key_event_creatFile);//退出子进程
    return ret;

}


int write_file()
{
    int ret=0;
    int fd=0;
    char readbuffer[128]={0};
    fd = open(path_of_file,O_RDWR | O_CREAT,0666) ;
    if(fd == -1)
	{
		printf("unexist %s\n",path_of_file);
	}	
	else
	{
		printf("open file1 success\n");
        printf("if you want exit edit ,please input “QUIT”\r\n");
        printf("please input string :\r\n");

        while(flag_of_QUITEDIT==0)
        {

            printf(">");
            memset(readbuffer,0,sizeof(readbuffer));
            fgets(&readbuffer[0],50,stdin);
            
            if(strncmp(readbuffer,"QUIT",strlen("QUIT"))==0)
            {
                flag_of_QUITEDIT=1;
            }
            //add"enter"to string
            {
                int len;
                len = strlen(readbuffer);
                readbuffer[len] = '\n';
                readbuffer[len+1] = '\0';
            }

            
            ret = write(fd,readbuffer,strlen(readbuffer));
            if(ret == -1)
            {
                perror("write");
                exit(-1);
            }
            if(flag_of_QUITEDIT==1)
            {
                close(fd);
                exit(Key_event_writeFile);
            }
        }

        }
}


int display_file()
{
    int fd=0;
    fd = system(path_of_file);
    //printf("fd = %d\r\n",fd);
    if(fd>0)
    {
        printf("cat file failed\r\n");
    }
    close(fd);
    exit(Key_event_displayFile);
}

int copy_file()
{
    int fd=0;
    int fdSRC=0;
    int fdDES=0;
    char *readBuf = NULL;
    //fd = system(path_of_file);
    //printf("fd = %d\r\n",fd);
    //使用lseek实现copy;源文件:p->buffer_param2;目标文件:p->buffer_param3
    fdSRC = open(p->buffer_param2,O_RDWR);//打开文件
    if(fdSRC==-1)
    {
        printf("src open failed\r\n");
    }
    else{
        //源文件打开成功
        int size = lseek(fdSRC,0,SEEK_END);//读取文件大小
        lseek(fdSRC,0,SEEK_SET);//把光标移动到文件头部
        readBuf = (char *)malloc(sizeof(char)*size + 8);//指针指向这么大的空间
        int n_read = read(fdSRC, readBuf, 1024);//把源文件的数据读取到buffer中

        fdDES = open(p->buffer_param3,O_RDWR|O_CREAT,0600);//创建目标文件
        int n_write = write( fdDES,readBuf,strlen(readBuf));//向目标文件写入信息
        close(fdSRC);
	    close(fdDES);
 	    exit(Key_event_copyFile);
    }


    
}


int delete_file()
{
    int fd=0;
    fd = system(path_of_file);
    //printf("fd = %d\r\n",fd);
    if(fd!=0)
    {
        printf("deete file failed\r\n");
    }
    exit(Key_event_deleteFile);
}

io.h

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#define Key_event_creatFile 0x01
#define Key_event_writeFile 0x02
#define Key_event_displayFile 0x03
#define Key_event_copyFile 0x04
#define Key_event_deleteFile 0x05
struct CMD_input{
    char CMD_CREAT[10];
    char CMD_CP[10];
    char CMD_DISPLAY[10];
    char CMD_DELETA[10];
    char CMD_WRITE[10];
};

struct buffer_param{
    char buffer_param0[10];
    char buffer_param1[10];
    char buffer_param2[10];
    char buffer_param3[10];
};
void log_test1();
int read_CMD();
int task_sch();
int creat_file();
int write_file();
int display_file();
int copy_file();
int delete_file();

 编译运行,如图父进程等待子进程退出后,打印出了子进程退出的状态;

如果子进程是被exit(2);退出的;

那么打印的printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));就是2.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/584621.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何创建新一代Web3企业

日前&#xff0c;我们对话了Sui基金会的增长负责人Koh Kim&#xff0c;对如何成功构建持续发展的企业等话题展开讨论。 您在Sui基金会的工作重点帮助开发者&#xff0c;让他们从产品开发的早期阶段成长为强大且具有潜力的企业领导者。可以简单分享一下您为此目标创建的计划吗&…

Linux进程地址空间——下篇

目录 一.深入了解进程地址空间&#xff1a; 单个进程与进程地址空间与物理内存之间的联系图&#xff1a; 多个进程与进程地址空间与物理内存之间的联系图&#xff1a; 二.为什么会存在进程地址空间呢&#xff1f; 作用1&#xff1a;进程地址空间的存在&#xff0c;保证了其他…

Flutter 笔记 | Flutter 文件IO、网络请求、JSON、日期与国际化

文件IO操作 Dart的 IO 库包含了文件读写的相关类&#xff0c;它属于 Dart 语法标准的一部分&#xff0c;所以通过 Dart IO 库&#xff0c;无论是 Dart VM 下的脚本还是 Flutter&#xff0c;都是通过 Dart IO 库来操作文件的&#xff0c;不过和 Dart VM 相比&#xff0c;Flutte…

6.1 进程的创建和回收

目录 进程概念 程序 进程 进程内容 进程控制块 进程类型 进程状态 常用命令 查看进程信息 进程相关命令 进程的创建和结束 子进程概念 子进程创建-fork 父子进程 进程结束-exit/_exit 进程结束-exit-示例1 进程结束-exit-示例2 进程回收 进程回收-wait 进程回…

企业数字化转型,为什么会加快商业智能BI的发展

对于企业数字化转型来说&#xff0c;数据是其中提到最多的词汇。当今世界&#xff0c;随着人们认识到数据的重要性&#xff0c;明白了数据发挥价值的方式及其意义&#xff0c;数据资产就成为数字化转型企业需要掌握利用的关键。 数据可视化 - 派可数据商业智能BI可视化分析平台…

服务windows服务+辅助角色服务

1、vs2022新建一个windows服务项目 2、修改服务参数 &#xff08;1&#xff09;AutoLog: 是否将事件写入到windows的事件日志中。 &#xff08;2&#xff09;canpauseandContinue:服务是否可以暂停和继续 3、添加服务安装程序 在界面内右击鼠标 新建一个服务、新建后如下图&a…

【运维】speedtest测试

目录 docker 布署 布署云端 docker布署 云端放置于已有容器里 librespeed/speedtest: Self-hosted Speedtest for HTML5 and more. Easy setup, examples, configurable, mobile friendly. Supports PHP, Node, Multiple servers, and more (github.com) docker 布署 获取…

探讨生产环境下缓存雪崩的几种场景及解决方案

本文首发自「慕课网」&#xff08;www.imooc.com&#xff09;&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注"慕课网"或慕课网公众号&#xff01; 作者&#xff1a;大能 | 慕课网讲师 缓存我们经常使用&#xff0c;但是有时候我们…

如何撤消 Git 中最新的本地提交?

在使用Git进行版本控制时&#xff0c;有时我们可能会犯下错误或者想要撤销最新的本地提交。Git提供了一些强大的工具和命令&#xff0c;使我们能够轻松地撤消最近的提交并修复错误。 本文将详细介绍如何在Git中撤消最新的本地提交。 步骤1&#xff1a;查看提交历史 在撤消最新…

Centos7安装Java8(在线安装避坑详细安装)

开篇语&#xff1a; 喜欢在一个明媚阳光的午后 坐在那夕阳斑驳的南墙下 听着风起 闻着花香 望着远山 身边是你 如此便觉得很好 1.查看目前环境 rpm -qa|grep jdk在这里我们会发现&#xff0c;原有系统安装有jdk&#xff0c;如果对于jdk有要求&#xff0c;我们就需要重新安装jdk…

Liunx网络基础(3)传输层(TCP/UDP)可靠传输、字节流传输等

传输层协议 传输层协议解析: 负责两端之间的数据传输; TCP/ UDP 1. UDP UDP: 用户数据报协议&#xff0c;无连接&#xff0c;不可靠&#xff0c;面向数据报传输 重点: 协议格式&#xff0c;协议特性&#xff0c;特性对于编程的影响 协议格式&#xff1a; 16位源端口 & 16位…

2023-05-29 用 fltk gui库编写一个打字练习程序

用 fltk gui库编写一个打字练习程序 前言一、FLTK GUI 库二、使用步骤1.引入库2.使用代码 总结 前言 给孩子练习键盘打字, 发现终端还是欠点意思, 研究了一下gui, 最终用 fltk库弄了一个. 对于没有接触过gui的人, 发现, 编程的逻辑和终端区别很大, 很繁琐, 可能需要适应适应,…

Windows远程Centos7图形化界面

一、centos7服务器安装tigervnc 1、更新yum源 yum update 2、安装tigervnc yum -y install tigervnc* 3、启动vnc vncserver &#xff08;1&#xff09;执行命令后需要输入密码 &#xff08;2&#xff09;再次输入密码 注意&#xff1a;密码一定要记住&#xff0c;方便以…

链表反转方法汇总

反转范围之前有节点&#xff0c;prev就指向该节点&#xff0c;没有就prevnull&#xff1b; 一、头插法 class Solution {public ListNode reverseList(ListNode head) {ListNode header new ListNode(-1);ListNode cur head;while(cur ! null) {ListNode tmp cur.next;cur.…

LabVIEWCompactRIO 开发指南第六章41 同步模块

同步模块 同时运行的模块每个通道有一个ADC&#xff0c;并且采集数据时通道之间没有明显的偏差。同步模块的两个子类别&#xff0c;按需和三角积分&#xff0c;通过SPI总线传输数据&#xff0c;并受到其他SPI总线模块的所有规格和挑战的约束。 按需转换 表6.1.具有按需转换的…

Postgresql源码(104)子连接提升过程pull_up_sublinks

1 场景构造 drop table student; create table student(sno int primary key, sname varchar(10), ssex int); insert into student values(1, stu1, 0); insert into student values(2, stu2, 1); insert into student values(3, stu3, 1); insert into student values(4, st…

模块化

一、目标 能够说出模块化的好处能够知道CommonJS规定了哪些内容能够说出Node.js中模块的三大分类各自是什么能够使用npm管理包能够了解什么是规范的包结构能够了解模块的加载机制 二、目录 模块化的基本概念Node.js中模块的分类npm与包模块的加载机制 1.模块化的基本概念 …

spring源码解读

深入了解Spring Bean Java bean和spring bean区别 Java bean的属性私有&#xff0c;只能通过get和set方法来对属性进行操作。Spring bean是由spring容器生成和管理的对象。 spring Bean的定义方式 xml文件 。 声明式。 bean注解。 声明式。 component注解。声明式。 Bea…

房产中介APP开发功能有哪些?

房产中介APP开发功能有哪些&#xff1f; 1. 发布信息。中介或房东通过房地产中介APP客户端发布出租房屋的相关信息。 2. 房屋搜查。根据不同类型的房源进行分类&#xff0c;如公寓、整租、合租、写字楼、办公楼等&#xff0c;也可以根据不同的位置信息、商圈、距…

2023年下半年软考高级需要报班吗?

首先&#xff0c;对于软考高级考试报班与否的问题&#xff0c;需要根据自身的情况来做出决定。如果你有较强的自学能力&#xff0c;且具备丰富的实际工作经验和技术知识&#xff0c;那么不报班也完全可以自学备考。但如果你对软件工程的知识掌握程度较低&#xff0c;或者时间紧…