• 操作系统:Linux进程与线程


    这里是一部分内容,还会做修改。

    一:目的及内容

    学习fork(),exec,pthread库函数的使用,阅读源码,分析fork,exec,pthread_create函数的机理

    代码实现:

    进程A创建子进程B

    子进程B与父进程A分别对应不同的可执行体:A打印Hello world,B实现sum累加

    进程B具有三线程,主线程创建新的线程1实现sum累加(从1到参数x),线程2监控输入参数x

    若输入x是非负整数,线程1开始计算;如果线程1正在计算前次程序,线程2的输入非负整数和最近一次的又不同,线程1应重新计算;若相同则不需要重新计算

    若输入字母p,则线程1暂停执行。

    输入字母e则线程1打印退出信息后整个进程A和B都退出

    若输入的是其他字符,则线程1打印一个输入错误提示,任务继续

    分析运行中各个执行体的处理器使用,内存使用等基本信息

    二 步骤

    参考

    Linux C编程--fork()详解 - 张勤一 - CSDN博客 

    [并发并行]_[pthread]_[对工作线程进行简单控制-暂停-继续-停止] - 心如止水 - CSDN博客

    Linux多任务编程(三)---exec函数族及其基础实验 - 王大壮的博客 - CSDN博客

    Linux多线程编程并传递多个参数实例 - blankqdb - 博客园

    有关pthread线程的暂停与恢复的讨论 - 一天 一小步 - CSDN博客

    根据题目要求,可知需要两个执行体A和B。根据模块化的原则先设计A,再设计B。

    1. 审题,根据题目要求,写了进程A的代码

    #include提供fork(),execlp()函数

    #include <sys/wait.h> 提供wait()函数

    #include 提供类型pid_t的定义

    代码比较简单,主要就是创建子进程,子进程用一个新的进程映像替换当前进程映像。


     

    2. 之后写子进程B的代码

    充分利用模块化的设计方法。

    先是头文件

    #include<pthread.h>提供pthread库函数

    而需要注意,gcc编译时加上-lpthread,因为pthread并非Linux默认的库


     

    之后是几个全局变量,减少线程间传递参数的麻烦。


     

    1.主线程

    功能是创建2个子线程,线程2监控输入,线程1打印信息和计算累加。

    当线程1,2都退出后主线程退出。

    使用pthread_create创建子线程。

    使用pthread_join等待线程结束


     

    2.线程2

    因为线程2要监控输入,所以先写线程2.

    线程2第一部分:

    主要进行输入的处理。

    详情见图片和代码的注释。

    这里用c++的string处理输入,因为没有限制输入类型


     

    线程2第二部分:

    根据输入确定func值。func作为全局变量调整线程1的工作状态

    同时根据recent和cal判断是否要重新计算。target是线程1从1开始的累加目标。


     

    线程2第三部分:

    根据第二部分得到的func调整线程1工作状态。

    func==2时,利用pthread_join()先等待线程1打印错误信息,再退出。

    pthread_suspend()  pthread_resume()函数是自己定义的函数,用以实现线程1暂停。暂停的实现具体解释见实验报告后续部分。


     

    3. 线程1

    第一部分:实现线程1的暂停。

    利用

    pthread_mutex_lock(),pthread_mutexunlock(),pthread_cond_wait(),pthread_cond_broadcast()实现线程的暂停。

    源码体现的暂停实现过程更清晰。


     

     

     

    第二部分:线程1进行累加,输出信息等操作

    sleep是为了体现p操作,两次输入相同,不同操作而设置。否则可能人输入的速度不如计算机计算速度,导致第二次输入还没到,就得出上一次的结果。


     

    综上,进程B结构如下

    void pthread_suspend(void)

    void pthread_resume(coid)

    void thread1(void* arg)

    void thread2(void*arg)

    int main()

    三.分析运行中各个执行体的处理器使用,内存使用等基本信息

    首先在终端运行进程A。


     

    pgrep 是通过程序的名字来查询进程的工具,一般是用来判断程序是否正在运行。在服务器的配置和管理中,这个工具常被应用,简单明了;

    然后打开另一个终端,pgrep -l A查看进程名和pid


     

    pstree -p 26638。以树状图显示进程,并显示进程pid。可见父子进程和线程的关系。


     

    ps -T -p 26639 可以查看进程B的线程信息。


     

    使用top查看进程cpu和内存信息。

    下图为示例:


     

    top命令的第三行,cpu状态:

    依次对应:

    us:user 用户空间占用cpu的百分比

    sy:system 内核空间占用cpu的百分比

    ni:niced 改变过优先级的进程占用cpu的百分比

    id:空闲cpu百分比

    wa:IO wait IO等待占用cpu的百分比

    hi:Hardware IRQ 硬中断 占用cpu的百分比

    si:software 软中断 占用cpu的百分比

    st:被hypervisor偷去的时间

    top命令第四行,内存状态:

    total,free ,used ,buff/cache

    依次对应:物理内存总量,空闲内存总量,使用中的内存总量,缓冲内存量

    进入top后,交互时,输入s,系统提示更改刷新间隔。输入0则不断刷新。


     

    top -p 26638查看pid为26638的进程(即A)的信息


     

    top -p - H 26639

    top命令可以实时显示各个线程情况。要在top输出中开启线程查看,请调用top命令的“-H”选项,该选项会列出所有Linux线程。在top运行时,你也可以通过按“H”键将线程查看模式切换为开或关。


     

    四 遇到的问题及解决:

    1.编译时出现c++11标准库未定义错误,因为编译器使用的库版本不同。


     

     

    解决:使用-l链接 stdc++


     

    2. gcc编译时报错


     

    解决:

    在32位模式时,int 和指针类型变量都占32位在64位模式下,int占32位,指针变量占64位


     

    3.如图


     

    又是-lstdc++解决

    五.实验结果记录:

    执行程序A。程序A 父进程fork 出子进程,之后打印Hello, world!然后执行wait(),等待子进程结束。

    子进程调用execlp,执行另一个执行体B。

    执行体B中线程2开始监控输入。

    输入15,是非负整数,之后线程1计算1累加到15.结果为120。120后跟着的15表明计算的是1-15累加。

    输入16,是非负整数,之后线程1计算1累加到16.结果为136。136后跟着的16表明计算的是1-16累加。

    输入18,之后输入20.线程2监控到由于20与18不同,故线程1不再进行1-18累加,而进行1-20累加。

    输出210.

    输入25,再输入25.线程2监控到25相同,不需要重新计算,打印信息“输入相同,不需要重新计算”。线程1计算第一个25,输出325.

    输入afd。线程2监控,属于其他字符,线程1打印错误信息“input wrong”。

    输入fg。线程2监控,属于其他字符,线程1打印错误信息“input wrong”。

    输入p,线程1暂停执行。打印信息“pause”表明线程1已暂停。

    输入123.线程2检测到是非负整数,先调用恢复函数解除线程1的暂停。之后打印信息“resume”表示线程1已经恢复。之后线程1执行1-123累加,输出7626.

    输入e。线程2检测到要退出。之后线程1打印信息“A and B exited”表示主进程,子进程都要退出。之后主进程和子进程都退出。

    结束。

  • 相关阅读:
    lambda表达式
    Java的MongoDB驱动及读写策略
    MongDB主从复制、复制集
    PL/SQL练习
    MySQL数据库MyISAM和InnoDB存储引擎的比较(转)
    Java的垃圾回收概述
    springMVC源码浅析
    ActiveMQ使用总结
    常用的缓存产品比较
    Nginx+tomcat负载均衡并动静态分离
  • 原文地址:https://www.cnblogs.com/lqerio/p/11117626.html
Copyright © 2020-2023  润新知