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

相关文章

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

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

如何更优雅地对接第三方API

如何更优雅地对接第三方API 本文所有示例完整代码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/third 我们在日常开发过程中,有不少场景会对接第三方的API,例如第三方账号登录,第三方服务等等。第三方服务会提供API或者SDK,我依稀记得早些年Maven还没那么广泛使用,通常要对接第三方

Java基础回顾系列-第五天-高级编程之API类库

Java基础回顾系列-第五天-高级编程之API类库 Java基础类库StringBufferStringBuilderStringCharSequence接口AutoCloseable接口RuntimeSystemCleaner对象克隆 数字操作类Math数学计算类Random随机数生成类BigInteger/BigDecimal大数字操作类 日期操作类DateSimpleDateForma

Restful API 原理以及实现

先说说API 再说啥是RESRFUL API之前,咱先说说啥是API吧。API大家应该都知道吧,简称接口嘛。随着现在移动互联网的火爆,手机软件,也就是APP几乎快爆棚了。几乎任何一个网站或者应用都会出一款iOS或者Android APP,相比网页版的体验,APP确实各方面性能要好很多。 那么现在问题来了。比如QQ空间网站,如果我想获取一个用户发的说说列表。 QQ空间网站里面需要这个功能。

京东物流查询|开发者调用API接口实现

快递聚合查询的优势 1、高效整合多种快递信息。2、实时动态更新。3、自动化管理流程。 聚合国内外1500家快递公司的物流信息查询服务,使用API接口查询京东物流的便捷步骤,首先选择专业的数据平台的快递API接口:物流快递查询API接口-单号查询API - 探数数据 以下示例是参考的示例代码: import requestsurl = "http://api.tanshuapi.com/a

WordPress开发中常用的工具或api文档

http://php.net/ http://httpd.apache.org/ https://wordpress.org/ https://cn.wordpress.org/ https://core.svn.wordpress.org/ zh-cn:开发者文档: https://codex.wordpress.org/zh-cn:%E5%BC%80%E5%8F%91%E8%80%

Java后端微服务架构下的API限流策略:Guava RateLimiter

Java后端微服务架构下的API限流策略:Guava RateLimiter 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 在微服务架构中,API限流是保护服务不受过度使用和拒绝服务攻击的重要手段。Guava RateLimiter是Google开源的Java库中的一个组件,提供了简单易用的限流功能。 API限流概述 API限流通过控制请求的速率来防止

Docker远程连接和Docker Remote Api

在Docker生态系统中一共有3种API:Registry API、Docker Hub API、Docker Remote API 这三种API都是RESTful风格的。这里Remote API是通过程序与Docker进行集成和交互的核心内容。 Docker Remote API是由Docker守护进程提供的。默认情况下,Docker守护进程会绑定到一个所在宿主机的套接字:unix:///v

Unity Post Process Unity后处理学习日志

Unity Post Process Unity后处理学习日志 在现代游戏开发中,后处理(Post Processing)技术已经成为提升游戏画面质量的关键工具。Unity的后处理栈(Post Processing Stack)是一个强大的插件,它允许开发者为游戏场景添加各种视觉效果,如景深、色彩校正、辉光、模糊等。这些效果不仅能够增强游戏的视觉吸引力,还能帮助传达特定的情感和氛围。 文档

基于MinerU的PDF解析API

基于MinerU的PDF解析API - MinerU的GPU镜像构建- 基于FastAPI的PDF解析接口 支持一键启动,已经打包到镜像中,自带模型权重,支持GPU推理加速,GPU速度相比CPU每页解析要快几十倍不等 主要功能 删除页眉、页脚、脚注、页码等元素,保持语义连贯对多栏输出符合人类阅读顺序的文本保留原文档的结构,包括标题、段落、列表等提取图像、图片标题、表格、表格标题自动识别