HomeWork ( 一) P46:Interlude: Process API

2024-01-25 04:10

本文主要是介绍HomeWork ( 一) P46:Interlude: Process API,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

总的来说这一页的习题就是让你看懂,我们有哪些API!以及这些API最基本的调用方法和特性。

Homework (Code)

In this homework, you are to gain some familiarity with the process management APIs about which you just read. Don’t worry – it’s even more fun than it sounds! You’ll in general be much better off if you find as much time as you can to write some code5, so why not start now?

Questions

  1. Write a program that calls fork(). Before calling fork(), have the main process access a variable (e.g., x) and set its value to some- thing (e.g., 100). What value is the variable in the child process? What happens to the variable when both the child and parent change the value of x?

  2. Write a program that opens a file (with the open() system call) and then calls fork() to create a new process. Can both the child and parent access the file descriptor returned by open()? What happens when they are writing to the file concurrently, i.e., at the same time?

  3. Write another program using fork(). The child process should print “hello”; the parent process should print “goodbye”. You should try to ensure that the child process always prints first; can you do this without calling wait() in the parent?

  4. Write a program that calls fork() and then calls some form of exec() to run the program /bin/lsSee if you can try all of the variants of exec(), including execl(), execle(), execlp(), execv(), execvp(), and execvP(). Why do you think there are so many variants of the same basic call?

  5. Now write a program that uses wait() to wait for the child process to finish in the parent. What does wait() return? What happens if you use wait() in the child?

  1. Write a slight modification of the previous program, this time using waitpid() instead of wait(). When would waitpid() be useful?

  2. Write a program that creates a child process, and then in the child closes standard output (STDOUT FILENO). What happens if the child calls printf() to print some output after closing the descriptor?

  3. Write a program that creates two children, and connects the standard output of one to the standard input of the other, using the pipe() system call.

解答
第 1/2 题 : 父进程和子进程共享“变量”、“文件”、“缓冲区”,但是文件这里是个坑,第一题变量就不说了,第二题中 fwrite 和 write的差别会导致输出不一样,比如
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>int main(int argc, const char * argv[]) {char *hello="hello\n";char *world="world\n";char *welcome = "welcome\n";FILE *fp;if((fp  = fopen("/Users/air/Desktop/OS3pieces/Process API Program in The Book/HomeWork2/test.txt", "at+"))== NULL){printf("OPEN ERROR!");return 0;}if(fwrite(welcome, strlen(welcome), 1, fp) < 1)printf("WRITE ERROR");int pid = fork();if(pid  < 0){printf("Fork created error!\n");}else if(pid == 0){printf("I am the child, my pid is %d\n",(int)getpid());if(fwrite(hello, strlen(hello), 1, fp) < 1)printf("WRITE ERROR");}else{printf("I am the parent, my child is %d, my own pid is %d\n", pid, (int)getpid());if(fwrite(world, strlen(world), 1, fp)< 1)printf("WRITE ERROR");}fclose(fp);return 0;
}
输出为:
welcome
world
welcome
hello

因为子进程的缓冲区内已经有了welcome,所以打印的时候会一起打印出来;

比如:把 fwrite 换成了 write之后:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>int main(int argc, const char * argv[]) {char *hello="hello\n";char *world="world\n";char *welcome = "welcome\n";FILE *fp;if((fp  = open("/Users/air/Desktop/OS3pieces/Process API Program in The Book/HomeWork22/test.txt", O_WRONLY))== NULL){printf("OPEN ERROR!");return 0;}if(write(fp,welcome, strlen(welcome)) < 1)printf("WRITE ERROR");int pid = fork();if(pid  < 0){printf("Fork created error!\n");}else if(pid == 0){printf("I am the child, my pid is %d\n",(int)getpid());if(write(fp,hello, strlen(hello)) < 1)printf("WRITE ERROR");}else{printf("I am the parent, my child is %d, my own pid is %d\n", pid, (int)getpid());if(write(fp,world, strlen(world))< 1)printf("WRITE ERROR");}fclose(fp);return 0;
}
输出为:
welcome
hello
world


再奉上一道腾讯的校招笔试题:分别打印多少个 “-” 和 “-\n”?

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>int main(){for(int i=0;i<2;i++){fork();printf("-");}return 0;
}
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>int main(){for(int i=0;i<2;i++){fork();printf("-\n");}return 0;
}

我觉得这里还是有些坑要小心点的。


第 3  题:  不使用wait()函数,让子程序先完成。 这道题很开放哈,我自己的做法是这样的,再父进程中再创建fork(), 代码如下:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>int main(int argc, const char * argv[]) {int pid = fork();if(pid  < 0){printf("Fork created error!\n");}else if(pid == 0){printf("I am the child, my pid is %d\n",(int)getpid());printf("Hello\n");}else{int id = fork(); //就是在父进程中,再次调用fork函数,那么fork函数执行完父程序后什么也没打印,然后再执行第一个子程序 hello ,再执行第二个子程序 goodbyeif(id == 0){printf("goodbye\n");}//int wc = wait(NULL); Instead of using wait function,make sure that the child proces excute first.printf("I am the parent, my child is %d, my own pid is %d\n", pid, (int)getpid());}return 0;
}
第 4 题:用exec族的6个函数实现一个功能,我觉得这位同学写的不错,直接就贴上来吧,看懂了自己肯定是能写的。

            https://blog.csdn.net/zjwson/article/details/53337212 点击打开链接

           代码仿照了一下,这个真的是超级超级基本的函数额,一定要注意的是路径的问题,当然记不住回去看看文档就好了,shell里文档的命令是:

man execl      


第 5 题:是关于wait() 函数的返回值的。同样有很详细的解答了已经:

           https://www.cnblogs.com/black-mamba/p/6886434.html  点击打开链接

            那么子进程中使用wait()当然是返回 -1 啦~~(如果子进程中没有再使用fork函数的话)

第 6 题:是关于waitpid () 函数的返回值的。同样有很详细的解答了已经:            

           https://blog.csdn.net/roland_sun/article/details/32084825 点击打开链接

           再父进程里试一下不同的 options 就可以看到父子进程不同的执行顺序。

           比如 options = WNOHANG, (这个WNOHANG肯定是个宏啦 - - 不知道是1 还是多少,我不想去看),那就还是父进程先行啦,都说了no hang 了!!不等你啊!!

int main(int argc, const char * argv[]) {int pid = fork();if(pid  < 0){printf("Fork created error!\n");}else if(pid == 0){printf("I am the child, my pid is %d\n",(int)getpid());}else{//wait(); 只要有一个进程终止,wait就会返回。也就是说只要wait接收到一个SIGCHLD信号,wait()就会返回。//对于两个或多个子进程的情况,需要调用wait两次或多次;//c. 如果它没有任何子进程,则立即出错返回;waitpid(pid,NULL,WNOHANG);//1、waitpid可等待一个特定的进程,而wait则返回任一终止子进程的状态//2、waitpid提供了一个wait的非阻塞版本//3、waitpid支持作业控制printf("I am the parent, my child is %d, my own pid is %d\n", pid, (int)getpid());}return 0;
}

第 7 题:关掉了STDOUT_FILENO之后,fprintf 当然是打印不出啦!!但是编译还是没问题的。

第 8 题:关于pipe ()函数,觉得这篇很棒,https://blog.csdn.net/skyroben/article/details/71513385 点击打开链接

      这张图真的太棒了:

 一秒看懂pipe!!         

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>int main(int argc, const char * argv[]) {int fd[2];int ret = pipe(fd);//fd参数返回两个文件描述符,fd[0]指向管道的读端,fd[1]指向管道的写端if(ret == -1){perror("pipe error\n");exit(1);}pid_t pid = fork();if(pid < 0){perror("fork failed\n");}if(pid == 0){ //Childclose(fd[0]);char * child = "I am a child";int j = 0;while(j < 5){write(fd[1], child, strlen(child) + 1);sleep(2);++j;}/*函数定义:ssize_t write (int fd, const void * buf, size_t count);函数说明:write()会把参数buf所指的内存写入count个字节到参数放到所指的文件内。返回值:如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。*/}else{close(fd[1]);char msg[100];int i = 0;while(i < 5){ssize_t s = read(fd[0], msg, 5);    //fd > 5, 父进程不会阻塞,while会执行多次,这个当然可以继续读啊,有的读干嘛不读。/*ssize_t s = read(fd[0], msg, 15),  fd < 5, 父进程会阻塞;当然要阻塞啊,阻塞等你子进程写东西过来嘛,多想想为什么。ssize_t read(int fd, void * buf, size_t count);read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。*/if (s>0){msg[s - 1] = '\0';}printf("%s\n", msg);i++;}}return 0;
}


这篇关于HomeWork ( 一) P46:Interlude: Process API的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/642048

相关文章

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

使用Python实现调用API获取图片存储到本地的方法

《使用Python实现调用API获取图片存储到本地的方法》开发一个自动化工具,用于从JSON数据源中提取图像ID,通过调用指定API获取未经压缩的原始图像文件,并确保下载结果与Postman等工具直接... 目录使用python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

python通过curl实现访问deepseek的API

《python通过curl实现访问deepseek的API》这篇文章主要为大家详细介绍了python如何通过curl实现访问deepseek的API,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编... API申请和充值下面是deepeek的API网站https://platform.deepsee

Java对接Dify API接口的完整流程

《Java对接DifyAPI接口的完整流程》Dify是一款AI应用开发平台,提供多种自然语言处理能力,通过调用Dify开放API,开发者可以快速集成智能对话、文本生成等功能到自己的Java应用中,本... 目录Java对接Dify API接口完整指南一、Dify API简介二、准备工作三、基础对接实现1.

一文详解如何在Vue3中封装API请求

《一文详解如何在Vue3中封装API请求》在现代前端开发中,API请求是不可避免的一部分,尤其是与后端交互时,下面我们来看看如何在Vue3项目中封装API请求,让你在实现功能时更加高效吧... 目录为什么要封装API请求1. vue 3项目结构2. 安装axIOS3. 创建API封装模块4. 封装API请求

springboot项目中常用的工具类和api详解

《springboot项目中常用的工具类和api详解》在SpringBoot项目中,开发者通常会依赖一些工具类和API来简化开发、提高效率,以下是一些常用的工具类及其典型应用场景,涵盖Spring原生... 目录1. Spring Framework 自带工具类(1) StringUtils(2) Coll

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo