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

相关文章

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

一分钟带你上手Python调用DeepSeek的API

《一分钟带你上手Python调用DeepSeek的API》最近DeepSeek非常火,作为一枚对前言技术非常关注的程序员来说,自然都想对接DeepSeek的API来体验一把,下面小编就来为大家介绍一下... 目录前言免费体验API-Key申请首次调用API基本概念最小单元推理模型智能体自定义界面总结前言最

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

5分钟获取deepseek api并搭建简易问答应用

《5分钟获取deepseekapi并搭建简易问答应用》本文主要介绍了5分钟获取deepseekapi并搭建简易问答应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1、获取api2、获取base_url和chat_model3、配置模型参数方法一:终端中临时将加

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

使用SpringBoot创建一个RESTful API的详细步骤

《使用SpringBoot创建一个RESTfulAPI的详细步骤》使用Java的SpringBoot创建RESTfulAPI可以满足多种开发场景,它提供了快速开发、易于配置、可扩展、可维护的优点,尤... 目录一、创建 Spring Boot 项目二、创建控制器类(Controller Class)三、运行

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大,但不同的语言在不同领域都有着自己的优势,为了强强联合,LabVIEW提供了强大的外部程序接口能力,包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等。通过DLL可以使用户很方便地调用C、C++、C#、VB等编程语言写的程序以及windows自带的大