Linux 环境编程深入
文章平均质量分 87
文件 I/O{Linux系统调用, Linux C库函数}; 进程{进程环境, 进程控制, 进程关系, 守护进程}; 信号; 线程{线程创建, 线程控制}; 高级I/O; 进程间通信{ System V IPC, Posix IPC}; Socket
绯青
给时光以生命
展开
-
Socket编程实践(13) --UNIX域协议
UNIX域协议 UNIX域套接字与TCP相比, 在同一台主机上, UNIX域套接字更有效率, 几乎是TCP的两倍(由于UNIX域套接字不需要经过网络协议栈,不需要打包/拆包,计算校验和,维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程, 而且UNIX域协议机制本质上就是可靠的通讯, 而网络协议是为不可靠的通讯设计的). UNIX域套接字可以在同一台主机上各进程之间传递文件描述符原创 2015-03-14 20:56:03 · 4268 阅读 · 2 评论 -
Socket编程实践(12) --UDP编程基础
UDP特点 无连接,面向数据报(基于消息,不会粘包)的数据传输服务; 不可靠(可能会丢包, 乱序, 重复), 但因此一般情况下UDP更加高效;UDP客户/服务器模型 UDP-API使用#include #include ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, str原创 2015-03-14 20:34:10 · 2966 阅读 · 0 评论 -
Socket编程实践(10) --select的限制与poll的使用
select的限制用select实现的并发服务器,能达到的并发数一般受两方面限制:1)一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。可以通过ulimit -n(number)来调整或者使用setrlimit函数设置,但一个系统所能打开的最大数也是有限的,跟内存大小有关,可以通过cat /proc/sys/fs/file-max 查看/**示例: getrlimit/setrlimit原创 2015-03-14 20:21:05 · 3744 阅读 · 0 评论 -
Socket编程实践(9) --套接字IO超时设置方法
引:超时设置3种方案1. alarm超时设置方法//代码实现: 这种方式较少用void sigHandlerForSigAlrm(int signo){ return ;}signal(SIGALRM, sigHandlerForSigAlrm);alarm(5);int ret = read(sockfd, buf, sizeof(buf));if (ret == -1原创 2015-03-14 19:53:23 · 4522 阅读 · 1 评论 -
Socket编程实践(8) --Select-I/O复用
五种I/O模型介绍(1)阻塞I/O[默认] 当上层应用App调用recv系统调用时,如果对等方没有发送数据(Linux内核缓冲区中没有数据),上层应用Application1将阻塞;当对等方发送了数据,Linux内核recv端缓冲区数据到达,内核会把数据copy给用户空间。然后上层应用App解除阻塞,执行下一步操作。 (2)非阻塞I/O[少用] 上层应用App将套接字设置成非阻塞模式, 然原创 2015-03-14 15:32:34 · 4224 阅读 · 0 评论 -
Socket编程实践(6) --TCP服务端注意事项
僵尸进程处理1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中添加 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法,解决僵尸进程signal(SIGCHLD,onSignalCatch);void onSignalCatch(int signalNumber){ wait(NULL);}3) 如果多个客户端同时原创 2015-03-14 15:22:54 · 3120 阅读 · 0 评论 -
Socket编程实践(5) --TCP粘包问题与解决
TCP粘包问题由于TCP协议是基于字节流且无边界的传输协议, 因此很有可能产生粘包问题, 问题描述如下 对于Host A 发送的M1与M2两个各10K的数据块, Host B 接收数据的方式不确定, 有以下方式接收: 先接收M1, 再接收M2(正确方式) 先接收M2, 再接收M1(错误) 一次性收到20k数据(错误) 分两次收到,第一次15k,第二次5k(错误) 分两次收到原创 2015-03-14 15:47:39 · 3984 阅读 · 0 评论 -
Socket编程实践(4) --多进程并发server
1.Socket地址复用int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname, const void *optval, so原创 2015-03-14 15:07:19 · 4158 阅读 · 0 评论 -
Socket编程实践(3) --Socket API
socket函数#include #include int socket(int domain, int type, int protocol);创建一个套接字用于通信参数: domain:指定通信协议族(protocol family),常用取值AF_INET(IPv4) type:指定socket类型, 流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字原创 2015-03-14 12:24:49 · 3392 阅读 · 0 评论 -
Socket编程实践(2) --Socket编程导引
什么是Socket? Socket可以看成是用户进程与内核网络协议栈的接口(编程接口, 如下图所示), 其不仅可以用于本机进程间通信,可以用于网络上不同主机的进程间通信, 甚至还可以用于异构系统之间的通信。 IPv4套接口地址结构 IPv4套接口地址结构通常也称为“网际套接字地址结构”,它以“sockaddr_in”命名,定义在头文件中//TCP/IP地址结构struct socka原创 2015-03-14 12:10:58 · 3514 阅读 · 2 评论 -
Socket编程实践(1) --TCP/IP简述
ISO的OSI OSI(open system interconnection)开放系统互联模型是由ISO国际标准化组织定义的网络分层模型,共七层, 从下往上为:OSI七层参考模型物理层(Physical Layer)物理层定义了所有电子及物理设备的规范,为上层的传输提供了一个物理介质,本层中数据传输的单位为比特(bit/二进制位)。属于本层定义的规范有EIA/TIA RS-232、RJ-4原创 2015-03-14 11:50:27 · 4714 阅读 · 0 评论 -
Socket编程实践(11) --epoll原理与封装
常用模型的特点 Linux 下设计并发网络程序,有典型的Apache模型(Process Per Connection,PPC), TPC(Thread Per Connection)模型,以及 select/polL模型和epoll模型。 1 、PPC/TPC 模型 这两种模型思想类似,就是让每一个到来的连接一边自己做事去,别再来烦我(详见本系列博客).只是 PPC 是为它开了一个进原创 2015-03-11 22:23:33 · 7667 阅读 · 7 评论 -
Socket编程实践(7) --Socket-Class封装(改进版v2)
本篇博客定义一套用于TCP通信比较实用/好用Socket类库(运用C++封装的思想,将socket API尽量封装的好用与实用), 从开发出Socket库的第一个版本以来, 作者不知道做了多少改进, 每次有新的/好的想法尽量实现到该库当中来; 而且我还使用该库开发出作者第一个真正意义上的基于Linux的Server程序[MyHttpd, 在后续的博客当中, 我一定会将MyHttpd的实现原理与实现原创 2015-03-10 20:54:01 · 6052 阅读 · 5 评论 -
Linux多线程实践(10) --使用 C++11 编写 Linux 多线程程序
在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程序,从保持着几 t 甚或几 p 的数据的数据库系统,到手机上的一个有良好用户响应能力的 app,为了充分利用每个 CPU 内核,都会想到是否可以使用多线程技术。这里所说的“充分利用”包含了两个层面的意思,一转载 2015-02-19 19:09:58 · 4962 阅读 · 0 评论 -
Linux多线程实践(9) --简单线程池的设计与实现
线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务(不止一个不同的任务)就是一个需要解决的关键问题,其实这就是一些"池化资源"原创 2015-02-19 18:15:35 · 4656 阅读 · 1 评论 -
Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
Posix条件变量int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);int pthread_cond_destroy(pthread_cond_t *cond);int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex原创 2015-02-19 18:02:38 · 3886 阅读 · 0 评论 -
Linux多线程实践(7) --多线程排序对比
屏障int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned count);int pthread_barrier_destr原创 2015-02-19 17:51:08 · 4887 阅读 · 1 评论 -
Linux多线程实践(6) --Posix读写锁解决读者写者问题
Posix读写锁int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);int pthrea原创 2015-02-19 17:44:25 · 4350 阅读 · 0 评论 -
Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题
Posix信号量Posix 信号量有名信号量无名信号量sem_opensem_initsem_closesem_destroysem_unlink sem_waitsem_post 有名信号量#include /* For O_* constants */#include /* For mode constants */#include sem_t *s原创 2015-02-19 17:24:07 · 4099 阅读 · 0 评论 -
Linux多线程实践(4) --线程特定数据
线程特定数据int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));int pthread_key_delete(pthread_key_t key);int pthread_setspecific(pthread_key_t key, const void *pointer);void * p原创 2015-02-19 17:11:01 · 4152 阅读 · 1 评论 -
Linux多线程实践(3) --线程属性
初始化/销毁线程属性int pthread_attr_init(pthread_attr_t *attr);int pthread_attr_destroy(pthread_attr_t *attr);线程分离属性int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);int pthread_a原创 2015-02-19 16:52:55 · 2474 阅读 · 0 评论 -
Linux多线程实践(2) --线程基本API
POSIX线程库 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”开头,要使用这些函数库,要通过引入头文,而且链接这些线程函数库时要使用编译器命令的“-lpthread”选项[Ubuntu系列系统需要添加的是”-pthread”选项而不是”-lpthread”,如Ubuntu 14.04版本,深度Ubuntu等] 1.pthread_createint pthr原创 2015-02-19 16:33:24 · 2894 阅读 · 0 评论 -
Linux多线程实践(1) --线程理论
线程概念 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列/指令序列”; 一切进程至少有一个执行线程;进程 VS. 线程 1.进程是资源分配(进程需要参与资源的竞争)的基本单位,而线程是处理器调度(程序执行)的最小单位; 2.线程共享进程数据,但也拥有自己的一部分(非常少O(∩_∩)O~)数据,如线程ID、程序计数器、一组原创 2015-02-19 16:20:42 · 3168 阅读 · 0 评论 -
Linux IPC实践(13) --System V IPC综合实践
实践:实现一个先进先出的共享内存shmfifo 使用消息队列即可实现消息的先进先出(FIFO), 但是使用共享内存实现消息的先进先出则更加快速; 我们首先完成C语言版本的shmfifo(基于过程调用), 然后在此基础上实现C++版本的ShmFifo, 将1块共享内存与3个信号量(1个mutext信号量, 1个full信号量, 1个empty信号量)封装成一个类ShmFifo, 然后编写各原创 2015-02-19 16:08:19 · 2186 阅读 · 0 评论 -
Linux IPC实践(12) --System V信号量(2)
实践1:信号量实现进程互斥父子进程执行流程如下:父进程子进程PPO(print)X(print)sleepsleepO(print)X(print)VVsleepsleep从图中可以看出, O或X总是成对出现的, 要么两个O, 要么两个X;/**P,V原语实现父子进程互斥使用终端**/// 程序代码int main(int argc,char *argv[]){ int semid原创 2015-02-19 15:58:27 · 2234 阅读 · 0 评论 -
Linux IPC实践(11) --System V信号量(1)
信号量API#include #include #include int semget(key_t key, int nsems, int semflg);int semctl(int semid, int semnum, int cmd, ...);int semop(int semid, struct sembuf *sops, unsigned nsops);semgetint s原创 2015-02-19 15:52:53 · 2485 阅读 · 1 评论 -
Linux IPC实践(10) --Posix共享内存
1. 创建/获取一个共享内存#include #include /* For mode constants */#include /* For O_* constants */int shm_open(const char *name, int oflag, mode_t mode);参数: name: 共享内存名字; oflag: 与open原创 2015-02-19 15:14:46 · 2227 阅读 · 0 评论 -
Linux IPC实践(9) --System V共享内存
共享内存API#include #include int shmget(key_t key, size_t size, int shmflg);void *shmat(int shmid, const void *shmaddr, int shmflg);int shmdt(const void *shmaddr);int shmctl(int shmid, int cmd, stru原创 2015-02-19 15:02:57 · 2551 阅读 · 0 评论 -
Linux IPC实践(8) --共享内存/内存映射
概述 共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据(如图)。 共享内存 VS. 其他IPC形式 用管道/消息队列传递数据 用共享内存传递数据 共享内存生成之后,传递数据并不需要再走Linux内核,共享内存允许两个或多个进程共享一个给定的原创 2015-02-19 14:51:20 · 3861 阅读 · 0 评论 -
Linux IPC实践(7) --Posix消息队列
1. 创建/获取一个消息队列#include /* For O_* constants */#include /* For mode constants */#include mqd_t mq_open(const char *name, int oflag); //专用于打开一个消息队列mqd_t mq_open(const char *name,原创 2015-02-18 19:45:00 · 2409 阅读 · 1 评论 -
Linux IPC实践(6) --System V消息队列(3)
消息队列综合案例消息队列实现回射客户/服务器 server进程接收时, 指定msgtyp为0, 从队首不断接收消息server进程发送时, 将mtype指定为接收到的client进程的pid client进程发送的时候, mtype指定为自己进程的pidclient进程接收时, 需要将msgtyp指定为自己进程的pid, 只接收消息类型为自己pid的消息;// client/server进程接收/原创 2015-02-18 19:26:29 · 2055 阅读 · 1 评论 -
Linux IPC实践(5) --System V消息队列(2)
消息发送/接收APImsgsnd函数int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);参数 msgid: 由msgget函数返回的消息队列标识码, 也可以是通过ipcs命令查询出来的一个已经存在的消息队列的ID号 msgp:是一个指针,指针指向准备发送的消息, msgsz:是msgp指向的消息长度, 注意原创 2015-02-18 19:19:13 · 2154 阅读 · 0 评论 -
Linux IPC实践(4) --System V消息队列(1)
消息队列概述 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法(仅局限于本机); 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值. 消息队列也有管道一样的不足: (1)每个消息的最长字节数的上限(MSGMAX); (2)系统中消息队列的总条数也有一个上限(MSGMNI); (3)每个消息队列所能够保存的总字节数是有上限的(MSGMNB) . 查看系原创 2015-02-18 17:58:18 · 2264 阅读 · 0 评论 -
Linux IPC实践(3) --具名FIFO
FIFO具名/命名管道 (匿名)管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道;命名管道是一种特殊类型的文件. 创建一个命名管道1)命名管道可以从命令行上创建: $ mkfifo 2)命名管道在程序里创建: #include #include原创 2015-02-18 17:45:07 · 1993 阅读 · 0 评论 -
Linux IPC实践(2) --匿名PIPE
管道概念 管道是Unix中最古老的进程间通信的形式,我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”, 管道的本质是固定大小的内核缓冲区; 如:ps aux | grep httpd | awk '{print $2}' 管道限制 1)管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 2)匿名管道只能用于具有共同祖先的进程(如父进程与fork原创 2015-02-18 17:35:29 · 1720 阅读 · 0 评论 -
Linux IPC实践(1) -- 概述
进程的同步与互斥 进程同步: 多个进程需要相互配合共同完成一项任务。 进程互斥: 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥;系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源, 而在进程中涉及到互斥资源的程序段叫临界区. Linux IPC发展 Linux下的进程通信手段基本上是从UNIX平台上的进程原创 2015-02-18 17:21:58 · 1611 阅读 · 0 评论 -
Linux信号实践(5) --时间与定时器
三种不同精度的睡眠1.sleep#include unsigned int sleep(unsigned int seconds);RETURN VALUE Zero if the requested time has elapsed, or the number of seconds left to sleep, if the call was interrupted by a sig原创 2015-02-18 16:19:39 · 1997 阅读 · 0 评论 -
Linux信号实践(4) --可靠信号
Sigaction#include int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);功能: sigaction函数用于改变进程接收到特定信号后的行为。参数 第一个参数为信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有原创 2015-02-18 16:07:04 · 1839 阅读 · 0 评论 -
Linux信号实践(3) --信号内核表示
信号在内核中的表示 执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。 注意,阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。信号在内核中的表示可以看作是这样的: 图-原创 2015-02-18 15:50:45 · 1925 阅读 · 0 评论 -
Linux信号实践(2) --信号分类
信号分类 不可靠信号Linux信号机制基本上是从UNIX系统中继承过来的。早期UNIX系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是: 1.进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。 2.因此导致, 早期UNIX下原创 2015-02-18 15:31:17 · 1803 阅读 · 0 评论