关闭

【github myLocker】select监听多个fd,互斥锁保护终端交互

标签: githubselect终端
225人阅读 评论(0) 收藏 举报
分类:

select监听多个fd

select用于多个fd的管理,检测哪个fd可读、可写,如果可读则接收消息(读),如果可写则输出消息(写)。
相关的函数:

int select(int nfds, fd_set *readfds, fd_set *writefds,
          fd_set *exceptfds, struct timeval *timeout);

void FD_CLR(int fd, fd_set *set);        /* 将某个fd从集合set中删除 */
int  FD_ISSET(int fd, fd_set *set);        /* 检测fd是否还在集合set中 */
void FD_SET(int fd, fd_set *set);        /* 将fd加入集合set中 */
void FD_ZERO(fd_set *set);                /* 将集合set清空 */

其中,select函数的选项timeout很有用,当其是NULL时,函数无限期阻塞;当其是{0,0}时,立即返回结果;当其是某一个大于0的时间值时,表示一定时间后return。
关于timeout:

struct timeval {
   long    tv_sec;         /* seconds */
   long    tv_usec;        /* microseconds */
};

应用:

    fd_set readfds;
    struct timeval tv = {0,0};

    while(1){
        memset(buff,0,BUFF_LEN);
        FD_ZERO(&readfds);
        FD_SET(main_send_fd,&readfds);
        FD_SET(main_lock_fd,&readfds);

        if(select(FD_SETSIZE,&readfds,NULL,NULL,&tv) <= 0){
            continue;
        }

        if(FD_ISSET(main_send_fd,&readfds)){    
            ret = recvfrom(main_send_fd,buff,BUFF_LEN,0,(struct sockaddr *)&client_addr,&client_addr_len);
            if(ret > 0){
                //...
            }
        }
        else if(FD_ISSET(main_lock_fd,&readfds)){
            ret = recvfrom(main_lock_fd,buff,BUFF_LEN,0,(struct sockaddr *)&locker_addr,&locker_addr_len);
            if(ret > 0){
                //...
            }
        }
    }

互斥锁保护终端交互

程序运行,未使用读写锁的情况下,输出信息是杂乱的,提示信息的输出和用户的输入被打断分开了。
如下:

[textRWThread] ret: 13, recv buff: write to .key
[lockerThread] ret: 7, recv buff: encrypt
[lockerThread] start encrypt text file...
[lockerThread] please enter filename to enrypt which file is put in folder:
[main] main recv "write ok" from pthTextRW.
[textCodeThread] pthTextCode -> main "prime numbers created" ok.
txt
[lockerThread] the file need to encrypt is folder/txt
[lockerThread] encrypt work finished.
[main] main recv "encrypt ok" from pthLocker.
[main] encrypt and prime number write work all finished!
[main] retval from textCode thread: 1
[main] retval from textRW thread: 1
[main] retval from Locker thread: 1

注意4-7行,当lockerThread线程输出please enter filename to enrypt which file is put in folder.要求用户输入文件名时,另外两个线程main, textCodeThread在屏幕上输出了信息,然后用户的输入文件名明显和LockerThread的提示信息分割开来。于是我们有这样的需求:怎样让提示信息的输出和文件名的输入成为一个原子操作(不可分割)。从本质上讲,线程都是在向屏幕写东西,这是典型的多人使用打印机问题。读写锁适用于读的次数多于写的次数,互斥锁则适用于多人使用同一资源的问题。
互斥锁的相关函数:

int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

互斥锁在使用完毕后,必须要对互斥锁进行销毁,以释放资源。即调用pthread_mutex_destroy()函数。
因为工程中的情况复杂,在屏幕上输入和输出,我们不能直接定义一个函数在函数里面上锁、解锁,再用线程调用此函数来实现不同线程独享stdout, stderr的资源,但是可以用全局变量mutex来实现上锁和阻塞,当一个线程已经对它上锁了,另一个线程试图再次上锁就会block。
code:
public.h:

pthread_mutex_t mutex_output;

main.c:

pthread_mutex_init(&mutex_output,NULL);  //初始化
/* 给输出动作上锁,然后解锁 */
pthread_mutex_lock(&mutex_output);
pthPrint();
printf("recv msg \"prime numbers created!\"\n");
pthread_mutex_unlock(&mutex_output);
...
pthread_mutex_destroy(&mutex_output);   /* 销毁互斥锁 */

pthTextCode.c输出的上锁情况和main类似。
pthLocker.c:

/* 给一个连续的输出和输入动作上锁,然后解锁 */    
pthread_mutex_lock(&mutex_output);
pthPrint();
printf("please enter filename to enrypt which file is put in folder: \n");
scanf("%s",filename);
pthread_mutex_unlock(&mutex_output);

之后的效果:

工程地址:https://github.com/theArcticOcean/myLocker

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Linux常见锁比较--自旋锁、互斥锁、信号量、临界区

自旋锁(SpinLock):锁的目的是为了保护共享资源,实现线程同步。自旋锁区别于其他锁的地方在于若某线程在未获得锁时将不断的询问(判断)自旋锁保持者是否释放了锁(获取锁操作将自旋在那里,不断地申请获...
  • liu_sheng_1991
  • liu_sheng_1991
  • 2016-08-23 15:36
  • 1763

C++ 临界区 多线程同步互斥

临界区(Critical Section) 保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线 程进入后其他所...
  • lzg13541043726
  • lzg13541043726
  • 2014-07-17 11:29
  • 7657

linux中多线程操作,互斥锁,条件锁

背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多线程 API 有一些细微和隐晦的差别。不注意这些 Linux 上的一些开发陷阱,常常会导致程序问题不穷,死锁不断...
  • wangqing_12345
  • wangqing_12345
  • 2017-03-30 17:51
  • 1410

Java--线程--线程控制,线程安全,线程同步,线程等待,线程交互,死锁,互斥锁,读写锁

多进程   每个进程间拥有独立的内存空间   0~4G  单核   系统将cpu所有时间分割为相同的时间片  由内核负责调度    线程属于进程内部  进程内部的所有线程共享...
  • zlQQhs
  • zlQQhs
  • 2012-12-03 20:38
  • 1745

Java--线程--线程控制,线程安全,线程同步,线程等待,线程交互,死锁,互斥锁,读写锁

转摘至:http://blog.csdn.net/zlqqhs/article/details/8253261 多进程   每个进程间拥有独立的内存空间   0~4G  单核   系统将...
  • liyong625175856
  • liyong625175856
  • 2013-12-23 11:02
  • 446

有别于互斥锁的自旋锁

  • 2014-09-30 14:29
  • 904B
  • 下载

select监听多个客户端 -- linux函数

使用select函数可以以非阻塞的方式和多个socket通信。程序只是演示select函数的使用,功能非常简单,即使某个连接关闭以后也不会修改当前连接数,连接数达到最大值后会终止程序。 1. 程序使...
  • ccy365263452
  • ccy365263452
  • 2015-07-11 11:35
  • 2085

利用select/poll监听多个设备详解

如果一个应用程序去处理多个设备,例如应用程序读取网路数据,按键,串口,一般能想到的有三种方法: 方法1: 串行+阻塞的方式读取: while(1) {  read(标准输入); read(网...
  • qq_28090573
  • qq_28090573
  • 2016-04-08 10:36
  • 1452

线程与互斥锁的应用

  • 2015-01-04 17:00
  • 10KB
  • 下载

linux和win32下通用的互斥锁Mutex封装

  • 2017-05-04 17:14
  • 8KB
  • 下载
    个人资料
    • 访问:327274次
    • 积分:8806
    • 等级:
    • 排名:第2521名
    • 原创:574篇
    • 转载:13篇
    • 译文:0篇
    • 评论:36条
    我的链接
    最新评论