《操作系统导论》实验二:进程API的使用

(1) 写个程序调用 fork()。调用 fork() 之前,主程序使用并设置变量x的值。子程序中x的值是多少?同时在父程序和子程序中修改x的值会发生什么?

// p1.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
  int x = 0;
  printf("father x is %d\n", x);	
  
  int rc = fork();
  if (rc < 0) {
    fprintf(stderr, "fork failed\n");
    exit(-1);
  } else if (rc == 0) {
    printf("child x is %d\n", x);	// 子进程
    x = 10;
    printf("child x has changed to %d\n", x);
    
  } else {							// 父进程
    x = 100;
    printf("father x has changed to %d\n", x);
  }
  exit(1);

  return 0;
}

在这里插入图片描述
可以看到,父进程和子进程的x初值均为0,并在各自的进程内变化为100和10,变量互不影响。

(2) 写个进程用 open() 打开一个文件,调用 fork() 创造新进程。父进程和子进程都能通过open() 访问该文件么?它们同时写入文件时会发生什么?

函数参数
openO_RDONLY只读模式、O_WRONLY只写模式、O_RDWR读写模式
read(int fd, void *buf, size_t count)读取文件名fd,读入内存空间名buff,读入字节数count
write (int fd,const void * buf,size_t count)写入文件名fd、读取内存空间名buff、读取字节数count
// p2.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int main() {
  int fd = open("./p2.rtf", O_RDWR);
  
  char buff[20];
  int rc = fork();
  if (rc < 0) {
    fprintf(stderr, "fork failed\n");
    exit(-1);   
  } else if (rc == 0) {
    read(fd,buff,20);
    printf("child process read:%s\n", buff);
    write(fd, "child process write ", 20);
  } else {
    read(fd,buff,20);
    printf("father process read:%s\n", buff);
    write(fd, "father process write\n", 20);
  }
  exit(1);
  
  return 0;
}

在这里插入图片描述
可以看到,只有父进程成功读取文件的内容,但父进程和子进程都成功地写入文件。

(3) 写另一使用 fork() 的程序。子进程应该打印"hello";父进程应该打印"goodbye"。程序保证先打印子进程的内容,并且不在父进程使用 wait()

// p3.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
  
  int rc = fork();
  if (rc < 0) {
    fprintf(stderr, "fork failed\n");
    exit(-1);   
  } else if (rc == 0) {  // 第1个子进程
    printf("hello\n");
  } else {
    int id = fork();     // 第2个子进程
    if (id == 0) printf("goodbye\n");
  }
  exit(1);
  
  return 0;
}

在这里插入图片描述
主程序main()调用fork()创建子进程1输出hello,然后父进程内再次调用fork()创建子进程2输出goodbye。父进程和子进程同时执行,从进程树的角度看,子进程2比子进程1处于更深位置,执行时间更长,从而保证先输出hello

(4) 写个程序调用fork()exec()函数簇重载程序 /bin/ls,并分析exec()函数簇区别。

#include <stdio.h>   // fprintf printf stderr
#include <stdlib.h>  // exit()
#include <unistd.h>  // fork() execvp()
#include <string.h>  // strdup()
#include <fcntl.h>   // file control options

int main(int argc, char *argv[]) {
  int rc = fork();
  if (rc < 0) {
    fprintf(stderr, "fork failed");
    exit(-1);
  } else if (rc == 0) {
    printf("child process called\n");

    char *myargs[2];
    myargs[0] = strdup("ls");      // program:"ls"
    myargs[1] = NULL;              // mark end of array
    execvp(myargs[0], myargs);
    printf("this shouldn't print out");
  } else {
    int wc = wait(NULL);
    printf("father process called\n");
  }

  return 0;
}

在这里插入图片描述
成功调用fork()创建子进程,并运行ls程序显示当前桌面工作目录下的文件。

(5)(6) 写程序在父进程调用wait()会返回什么?如果在子进程中调用wait()会发生什么?如何使用waitpid()使其发挥与wait()的作用?

父进程调用wait()返回子进程的PID,子进程调用wait(),因为没有可以等待结束的进程,所有出错返回-1。waitpid()的函数原型为waitpid(pid_t pid,int *status,int options),设定pid为-1,options为0,则waitpid()函数就完全退化成了wait()函数。

(7) 写程序创建子进程,在子进程中关闭标准输出STDOUT_FILENO会对printf()有什么影响?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/wait.h>

int
main(int argc, char *argv[])
{
    int rc = fork();
    if (rc < 0) {
      fprintf(stderr, "fork failed\n");
      exit(1);
    } else if (rc == 0) {
      close(STDOUT_FILENO); 
      printf("child process called\n");
    } else {
      printf("father process called\n");
    }
    return 0;
}

在这里插入图片描述
可以看出只有父进程的printf()语句得到输出,而子进程的printf()语句因为关闭STDOUT_FILENO得不到输出。

(8) 写程序创建两个子进程,使用pipe()将一个进程的标准输出作为另一个进程的标准输入。
学完管道相关知识回来。。。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值