zoukankan      html  css  js  c++  java
  • 实验六 进程基础

    项目 内容
    这个作业属于哪个课程 [2020春季Linux系统与应用]
    这个作业的要求在哪里 <实验六作业要求>
    学号-姓名 17041503-李美霞
    作业学习目标 1.掌握Linux系统环境C语言编程概念
    2.学习Linux系统进程概念

    1. 请举例说明静态链接库的创建与使用。

      ar:建立,修改档案或从档案中抽取成员
      ar -r :替换归档文件中已有的文件或加入新文件
      ar -t :显示归档文件内容

      举例:

      //文件名:add.c,加法
      int add(int a,int b){
      return a+b;
      }
      
      //文件名:sub.c,减法
      int sub(int a,int b){
      return a-b;
      }
      
      //文件名:main.c
      #include <stdio.h>
      int add(int a,int b);
      int sub(int a,int b);
      int main(){
      printf("3 + 1 = %d
      ",add(3,1));
      printf("3 - 1 = %d
      ",sub(3,1));
      return 0;
      }
      

    2. 请举例说明共享库的创建与使用。

      开始的目录结构:

      //文件名:common.h
      #ifndef _COMMON_
      #define _COMMON_
      int add(int a,int b);
      int sub(int a,int b);
      #endif
      
      //文件名:add.c
      int add(int a,int b){
      return a+b;
      }
      
      //文件名:sub.c
      int sub(int a,int b){
      return a-b;
      }
      
      //文件名:main.c
      #include<stido.h>
      #include"common.h"
      int main(){
      printf("3+1=%d
      ",add(3,1));
      printf("3-1=%d
      ",sub(3,1));
      }
      

      创建共享库:


      使用自己的共享库:

      方式一:

      方式二:

    3. 编程实现一个简单文件复制命令。

      //文件名:mycp.c
      #include <unistd.h> 
      #include <sys/types.h> 
      #include <sys/stat.h> 
      #include <fcntl.h>
      #include <stdio.h> 
      #define BUFFERSIZE 4096 
      int main(int argc, char* argv[]) {
      if (argc != 3) { 
      printf("usage:
       mycp src dst
      "); 
      return 1;
      }
      int srcfd = open(argv[1], O_RDONLY); 
      if (srcfd == -1) { 
      perror("open");
      return 1; 
      }
      int dstfd = open(argv[2], O_CREAT | O_WRONLY, 0666); 
      if (dstfd == -1) { 
      close(srcfd); 
      perror("open"); 
      return 1; 
      }
      int len = 0;
      char buffer[BUFFERSIZE] = {0}; 
      while((len = read(srcfd, buffer, BUFFERSIZE)) > 0) {
      if (write(dstfd, buffer, len) != len) {
      perror("write error"); 
      return 1; 
      }
      }
      if (len < 0) {
      perror("read error"); 
      return 1;
      }
      close(srcfd); // 关闭文件 
      close(dstfd);
      return 0; 
      }
      

      mycp.c文件复制前:

      复制后(test文件):

    4. 使用fork创建一个子进程,进程创建成功后父子进程分别输出不同的内容。

      fork:创建一个子进程

      ///文件名:fork1.c
      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      int main(){
      pid_t pid;
      printf("[%d]:Begin! 
      ",getpid());
      fflush(NULL);
      pid = fork();
      if(pid<0)
      {
      perror("fork()");
      exit(1);
      }
      else if(pid > 0)
      {
      printf("[%d]:Parent process if working!
      ",getpid());
      }
      else
      {
      printf("[%d]:Child process if working!
      ",getpid());
      }
      printf("[%d]:Finish!
      ",getpid());
      return 0;
      }
      

      全缓冲:
      全缓冲指的是系统在填满标准IO缓冲区之后才进行实际的IO操作;
      注意,对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。
      行缓冲:
      在这种情况下,标准IO在输入和输出中遇到换行符时执行IO操作;
      注意,当流涉及终端的时候,通常使用的是行缓冲。
      

      (1)删除fork1.c文件中 fflush(NULL); 这一行后运行结果为:

      (2)继续删除fork1.c文件中 “ printf("[%d]:Begin! ",getpid()); ” 这一句中的“ ”结果为:

    5. 使用fork创建多个子进程。

      这里请大家分析假如有下列代码段:

      int i;
      pid_t pid;
      for (i = 0; i < 3; i++) 
      pid = fork();
      

      上面代码段会产生多少子进程?
      会产生: 2^3-1=7个子进程。

      //文件fork2.c
      
      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      int main(){
      int i;
      pid_t pid;
      printf("[%d] Begin! 
      ",getpid());
      for (i = 0;i < 3; i++)
      {
      if((pid = fork()) ==0 )
      break;
      }
      if(pid<0)
      {
      perror("fork()");
      exit(1);
      }
      else if(pid > 0)
      {
      printf("[%d] Parent process is working!
      ",getpid());
      }
      else
      {
      printf("[%d] Child process %d is working!
      ",getpid(),i);
      }
      return 0;
      }
      

      用sleep函数来控制进程输出顺序:

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      int main(){
      int i;
      pid_t pid;
      printf("[%d] Begin! 
      ",getpid());
      for (i = 0;i < 3; i++)
      {
      if((pid = fork()) ==0 )
      break;
      }
      if(pid<0)
      {
      perror("fork()");
      exit(1);
      }
      else if(pid > 0)
      {    
      sleep(3);
      printf("[%d] Parent process is working!
      ",getpid());
      }
      else
      {
      sleep(i);
      printf("[%d] Child process %d is working!
      ",getpid(),i);
      }
      return 0;
      }
      

    6. 在 fork 之前以写的方式创建了一个文件 test.txt。然后 fork 出的子进程立即向文件中写入“world”,然后睡眠5秒。而父进程在 fork 后睡眠3秒后向 test.txt 写入 "hello",并关闭描述符。子进程恢复后,又向 test.txt 文件中写入 "lalala"后关闭描述符,结束。

      //文件forkwrite.c
      
      #include <unistd.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      #include <stdio.h>
      int main() {
      int fd = open("test.txt",O_WRONLY | O_CREAT,0664);
      if (fd == -1){
      perror("open");
      return 1;
      }
      printf("I'm father
      ");
      printf("before fork
      ");
      pid_t pid = fork();
      if (pid > 0){
      sleep(3);
      printf("I'm father; I'm writing test.txt...
      ");
      write(fd, "hello", 5);
      close(fd);
      }
      else if (pid ==0){
      printf("I'm child; I'm writing test.txt...
      ");
      write(fd, "world", 5);
      sleep(5);
      write(fd, "lalala", 6);
      close(fd);
      }
      else {
      perror("fork");
      return 1;
      }
      return 0;
      }
      

    7. 分别在主函数中使用execvp启动ls命令以及使用fork函数产生子进程调用execvp启动ls

      (1)使用execvp启动ls命令:

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      int main(){
      char* argv[] = {"ls","-l",NULL};
      if (execvp("ls",argv) == -1){
      perror("exec");
      return 1;
      }
      return 0;
      }
      

      (2)使用fork函数产生子进程调用execvp启动ls命令:

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      int main(){
      char* argv[] = {"ls","-l",NULL};
      pid_t pid = fork();
      if (pid > 0){
      printf("I'm father
      ");
      }
      else if (pid == 0) {
      printf("I'm child
      ");
      if (execvp("ls",argv) == -1){
      perror ("exec");
      return 1;
      }
      }
      else {
      perror("fork");
      return 1;
      }
      return 0;
      }
      

    8. 创建5个僵尸进程,并在终端通过ps axf命令查看僵尸进程信息。

      #include <unistd.h>
      #include <stdio.h>
      #include <string.h>
      int main() {
      printf("before fork
      ");
      pid_t pid, n = 5;
      while(n--) {
      pid = fork();
      if (pid == 0)
      break;
      else if (pid < 0){
      perror("fork");
      return 1;
      }
      }
      if (pid == 0) {
      printf("hello, I'm child %d; my father is %d
      ", getpid(),getppid());
      //getpid()  获取当前进程的pid
      //getppid() 获取当前进程的父进程的pid
      return 0;
      }
      while(1) {
      sleep(3);
      printf("hello, I'm father %d
      ", getpid());
      }
      return 0;
      }
      

      在终端中新建一个窗口,输入:

      ps axf		//显示进程见关联的树状结构图
      

    9. 通过wait来清理僵尸进程。

      wait(等待子进程中断或结束)
      (1)表头文件:
      #include<sys/types.h>
      #include<sys/wait.h>
      (2)定义函数: pid_t wait (int * status);
      (3)函数说明:
      wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status可以设成NULL。
      (4)返回值:
      如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1,失败原因存于errno 中。
      
      #include <unistd.h>
      #include <stdio.h>
      #include <string.h>
      #include <sys/wait.h>
      #include <sys/types.h>
      int main() {
      printf("before fork
      ");
      pid_t pid, n = 5;
      while(n--) {
      pid = fork();
      if (pid == 0)
      break;
      else if (pid < 0) {
      perror("fork");
      return 1;
      }
      }
      if (pid == 0) {
      printf("hello, I'm child %d;my father is %d
      ",getpid(),getppid());
      return 0;
      }
      while(1) {
      sleep(3);
      pid = wait(NULL);
      if (pid == -1) {
      perror("wait");
      sleep(10);
      printf("I'm father %d;I have wiped out all zombies
      ",getpid());
      return 1;
      }
      printf("Hello, I'm father %d; child %d exit
      ",getpid(),pid);
      }
      return 0;
      }
      
      

    10. 父进程通过waitpid函数等待特定子进程结束,若该子进程不结束,父进程一直阻塞。

      waitpid
      (1)函数功能:用来等待某个特定进程的结束
      (2)函数原型:
          pid_t waitpid(pid_t pid, int *status, int options);
      (3)参数:
          status如果不为空,会把状态信息写到它指向的位置
          options允许改变waitpid的行为,最有用的一个选项是WNOHANG,它的作用是防止waitpid把调用者的执行挂起.
      (4)返回值:成功返回等待子进程的pid,失败返回-1
      
      #include <stdio.h>
      #include <signal.h>
      #include <unistd.h>
      #include <errno.h>
      #include <sys/types.h>
      #include <sys/wait.h>
      #include <stdlib.h>
      void handler(int sig)
      {
      pid_t pid;
      while ((pid = waitpid(-1,NULL,WNOHANG)) > 0)
      {
      printf("wait child sucess : %d
      ",pid);
      
      }
      }
      int main()
      {
      signal(SIGCHLD,handler);
      pid_t pid = fork();
      if (pid == 0)
      {
      printf("child1 pid : %d
      ",getpid());
      sleep(3);
      exit(1);
      }
      pid_t pid2 = fork();
      if (pid2 == 0)
      {
      printf("child2 pid2 : %d
      ",getpid());
      sleep(5);
      exit(2);
      }
      pid_t pid3 = fork();
      if (pid3 == 0)
      {
      printf("child3 pid3 : %d
      ",getpid());
      sleep(7);
      exit(3);
      }
      printf("father pid : %d
      ",getpid());
      while (1)
      {
      printf("father do self
      ");
      sleep(1);
      }
      return 0;
      }
      

  • 相关阅读:
    成绩单问题
    详细介绍Linux shell脚本基础学习(一)
    千万级并发连接的秘密
    前段面试题
    cat 命令
    面试的一个网页设计师
    准备准备
    ls显示文件
    [HDU 1010 ]Tempter of the Bone
    Linux下的绘图(流程图、UML、mindmap)工具
  • 原文地址:https://www.cnblogs.com/lmxdbk/p/12829499.html
Copyright © 2011-2022 走看看