zoukankan      html  css  js  c++  java
  • 2019-2020-1 20175302 20175314 20175316 实验三 并发程序

    2019-2020-1 20175302 201752314 20175316 实验三 并发程序

    实验三 并发程序-1

    实验内容

    学习使用Linux命令wc(1);
    基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端;
    客户端传一个文本文件给服务器;
    服务器返加文本文件中的单词数。

    设计实现

    • 命令参数
      -c:统计字节数
      -l:统计行数
      -m:统计字符数。这个标志不能与 -c 标志一起使用。
      -w:统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串
      -L:打印最长行的长度
      -help:显示帮助信息
      --version:显示版本信息

    • 实现伪代码
      int main() { fd = fopen()//打开文件; fscanf()//对文件的内容以字符串的形式进行读取 if..count++//设置条件,当满足字符串条件时计数; }
      对于wc -w功能与我们统计单词个数相似,而其实现时:由' ',' ',' ',' '作为分隔符
      统计单词个数时,除上述分隔符,还加入了文本文件中常见的符号:'!','"','?','.',',','(',')',':',';','-'作为分隔符

    • 实现wc -w

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #define BUFFERSIZE 1024
    
    int main()
    {
        FILE *fp;
        char ch;
        char filename[100];
        int flag=0,num=0;
            printf("input filename: ");
        scanf("%s",filename);
        if((fp = fopen(filename,"r"))==NULL)
        {
            printf("Failure to open %s
    ",filename);
            exit(0);
        }
        while((ch=fgetc(fp))!=EOF)
        {
            if(ch==' ' || ch=='
    ' || ch=='	' || ch=='
    ')
            {
                flag=0;
            }
            else
            {
                if(flag==0)
                {
                    flag=1;
                    num++;
                }
    
            }
    
        }
        printf("%c
    ",num+48);
        fclose(fp);
        return 0;
    }
    
    • wc txt

    • 实现单词个数统计

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #define BUFFERSIZE 1024
    /*int num=0;
    void wc(char buffer[],int size)
    {
        int i,flag=0;
        for(i=0;i<size;i++)
        {
            if(buffer[i]==' ' || buffer[i]=='
    ' || buffer[i]=='	' || buffer[i]=='' || buffer[i]=='!' || buffer[i]=='?' || buffer[i]=='"' || buffer[i]=='.' || buffer[i]== ',' || buffer[i]==':' || buffer[i]=='(' || buffer[i]==')' || buffer[i]==';' || buffer[i]=='■ ' || buffer[i]=='•' )
            {
                flag=0;
            }
            else
            {
                if(flag==0)
                {
                    num++;
                }
                flag=1;
            }
        }
        return num;
    }*/
    int main()
    {
        FILE *fp;
        char ch;
        char filename[100];
        int flag=0,num=0;
            printf("input filename: ");
        scanf("%s",filename);
        if((fp = fopen(filename,"r"))==NULL)
        {
            printf("Failure to open %s
    ",filename);
            exit(0);
        }
        while((ch=fgetc(fp))!=EOF)
        {
            if(ch==' ' || ch=='
    ' || ch=='	' ||  ch=='!' || ch=='?' || ch=='"' || ch=='.' || ch== '\,' || ch==':' || ch=='(' || ch==')'     || ch==';' || ch=='-')
            {
                flag=0;
            }
            else
            {
                if(flag==0)
                {
                    flag=1;
                    num++;
                }
    
            }
    
        }
        printf("%d
    ",num);
        fclose(fp);
        return 0;
    }
    
    • 客户端和服务器的通信过程

    • 运行结果

    实验三 并发程序-2

    实验内容

    使用多线程实现wc服务器并使用同步互斥机制保证计数正确;
    对比单线程版本的性能,并分析原因。

    多线程

    • 同步
      直接制约关系
      加入同步机制主要是为了在多线程程序中,如果需要对某个共享资源C进行同步访问,如果系统没有调度到B,A也是没有可能访问C的,必须等B调度到之后,A才可能重新访问。

    • 互斥锁
      主要用来保护临界资源
      临界资源,就是有可能多个线程都需要访问的数据地址,也有可能是某一段代码,执行这段代码有可能会改变多个线程都需要访问的数据。

    • 多线程实现wc服务器时,会出现多个客户端同时像服务器传送文件的情况,需要根据发送的不同文件名创建新的接收文件,并要确立好调度顺序关系

    运行截图

    • 对比单线程版本的性能,并分析原因
    • 原因:所有数据结构的生存期,以及对这些数据结构的access,都用这一根逻辑线程,不需要考虑数据结构的race。把任何耗时的操作都给其他线程(IO线程、定时器线程,DB线程等)做,做完之后向事件队列(多线程安全的队列,其他线程是生产者,逻辑线程是消费者)丢事件。
    • 多线程逻辑设计的思路:
      所有数据结构的生存期,以及对这些数据结构的access,不一定在一根线程。
      需要考虑数据结构的race。
      网络事件、定时器事件唤醒工作线程(一般通过iocp或者epoll来唤醒)执行所有工作,一般不需要交换到其他线程。很显然,单线程逻辑多了一层事件队列交换,会增加延迟,以及所有的逻辑都在一根线程上跑,逻辑被阻塞也会带来延迟。其实吞吐量对于rpc来说,是个宏观的概念,尽可能快地消费网络消息就会提升吞吐量。
      对于高并发的程序,是无法忍受单线程逻辑。

    实验三 并发程序-3

    实验内容

    • 交叉编译多线程版本服务器并部署到实验箱中;
    • PC机作客户端测试wc服务器。

    实验步骤

    1.将实验箱与电脑相连,参照[实验一 开发环境的熟悉]的步骤操作,确保目标机(超级终端)和宿主机(虚拟机Ubuntu)能相互ping通(实验箱IP为192.168.0.232,Ubantu的IP为192.168.0.230)。

    2.修改客户端IP段代码。
    3.用交叉编译器arm-none-linux-gnuenbi-gcc编译server.c

    4.参照[实验一 开发环境的熟悉],挂载共享目录,通过NFS把宿主机中的程序运行目录映射到目标机中。
    5.在超级终端运行服务器armserve,在Ubantu运行客户端。

    实验中遇到的问题和解决方案

    • 问题一:多线程编译中已添加头文件<pthread.h>可是编译的时候却还是报错“对pthread_create未定义的引用”。
    • 原因:pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a。
    • 解决方案:所以在使用pthread_create创建线程时,在编译中要加-lpthread参数:
      gcc XXX.c -lpthread -o XXX

    实验心得与体会

    这次实验使我更加深刻地意识到知识之间的关联性是有多么的密切,比如这次的pthread库。它不是Linux系统默认的库,连接时需要使用静态库libpthread.a,所以在线程函数在编译时,需要使用“-lpthread”链接库函数。不经常巩固以往的知识点,它对你依旧只是陌生人。
  • 相关阅读:
    Keil的使用-1创建项目和工程
    UICollectionView进阶练习
    UICollectionView基础API笔记
    UICollectionView笔记2
    UICollectionView笔记1
    OC与JS交互之WKWebView
    OC与JS交互之JavaScriptCore
    OC与JS交互之UIWebView
    OC与JS交互前言
    最牛B的编码套路
  • 原文地址:https://www.cnblogs.com/sms369/p/11923868.html
Copyright © 2011-2022 走看看