关于c:C语言服务器编程必备常识

40次阅读

共计 5375 个字符,预计需要花费 14 分钟才能阅读完成。

入门

  • 蕴含了正确的头文件只能编译通过,没链接正确的库链接会报错。
  • 一些罕用的库 gcc 会主动链接。
  • 库的缺省门路 /lib /usr/lib /usr/local/lib
  • 不晓得某个函数在那个库能够 nm -o /lib *.so | grep 函数名
  • man sin 会列出蕴含的头文件和链接的库名。man 2 sin 2 示意零碎调用,3 示意 c 库函数
  • 一旦子过程被创立,父子过程一起从 fork 处被创立。创立子过程为了抢夺资源。
  • 重定向用 dup2 函数
  • kill - l 查看信号品种
  • pthread_mutex 不跨过程,ipc 中的信号量跨过程,但 linux 不反对无名信号量。信号灯的主要用途是爱护临界资源。多过程拜访共享内存,用信号量同步。
  • alarm(5)5 秒后向本人发送 SIGALARM 信号,缺省解决是完结过程,不自定义就会完结过程。通过对信号集加减信号,确定信号屏蔽字。在信号处理程序被调用时,操作系统建设的新信号屏蔽字包含正在被递送的信号,如果此时这个信号再次发生,将阻塞到前一个解决完,屡次产生不排队只解决一次。sa_mask 会被加到信号屏蔽字中。
  • netstat -an|grep A |grep ESTABLISHED | grep B,查看 ip 为 A 的服务器是否在端口 B 建设了连贯
  • 因为咱们的连贯都是常连贯,故能够依照客户端与服务器端建设的连贯端口进行判断。
  • IP 协定是网络层协定,次要发送数据包。UDP 基于 IP 协定,用在传输层。TCP 协定建设在 IP 协定之上,牢靠的、按程序发送的。
  • TCP 连贯三次握手:客户机向服务器发包。服务器给客户机回包。客户机收到包,向服务器发送确认信息实现连贯。服务器收到确认信息也实现连贯。
  • ioctl 能够管制所有文件描述符的状况。
  • 循环服务器:UDP 服务器,UDP 是非面向连贯的,没有一个客户机能够老是占着服务器。
  • TCP 循环服务器一次只能解决一个,close 后能力解决下一个。
  • TCP 并发服务器:fork 子过程来解决。创立子过程耗费资源。
  • 并发服务器:多路 IO 复用。
  • 当咱们创立一个失常的 TCP 套接字的时候,咱们只解决内容,不负责 TCP 头部和 ip 头部,本人创立头部应用 setsockopt。
  • 网络程序个别是多过程加上多线程。
  • g++ 参数 -pg 产生 gprof 性能信息,gprof 如同是 g ++ 自带的
  • (gdb)make 使你能不退出 gdb 就能产生就从新产生可执行文件,shell 不退出 gdb 就执行 shell
  • file a.out 能够在 gdb 模式下载入程序。
  • 服务器端:socket->bind->listen【建设监听队列,监听 socket】->【返回连贯 socket】accept【从监听队列取申请,胜利时返回新的 socket,与传入的第一参数不同,标识被承受的这个连贯】
  • 客户端:socket->connect

进阶

  • linux 中代替数据库管理文件可能会呈现文件数超过 linux 可治理数的问题。
  • tcpip 协定族:下层协定应用上层协定提供的服务。
  • 应用层的货色最初须要在内核中实现,会须要利用空间和内核空间的切换。
  • IP 数据太长要分片。IP 协定的外围是数据报路由。路由表、跳转、自动更新。
  • socket 含意 ip:port。称其为 socket 地址。
  • 字节序是按字节思考的,和位无关。cpu 累加器一次装载 4 字节(32 位机)。
  • 网络上传的肯定是大端字节序,各主机按本身状况转化。java 虚拟机采纳大端字节序。
  • 不同输出调用两次函数,如果发现前面后果笼罩后面后果,阐明函数不可重入。函数外部如果用动态变量存储后果,就不可重入。
  • 将一个地址和 socket 绑定称为给 socket 命名。0-1023 端口普通用户不能应用,有默认用处。
  • accept 只是从监听队列中取出连贯,不管连贯处于何种状态。connect(fd,..) 一旦连贯建设胜利,fd 就惟一标识了这个连贯,客户端就能够读写 fd 和服务器通信。
  • 对 socket 执行 close 只缩小连接数,fork 会使援用数加 1。无论如何都要终止连贯用 shutdown。
  • read 和 write 同样实用于 socket。用于 TCP 数据流的是 send recv。UDP 数据是 recvfrom sendto。
  • 没有过程读管道的时候【例如 close(fd[0]) 了】还往管道写数据将引发 SIGPIPE。
  • 把 STDOUT_FILENO 敞开,dup(连贯 socket),这时 dup 返回最小可用描述符 1【返回的文件描述符和原有描述符指向雷同文件】,此时 printf 回返回给客户端,而不是打印在屏上。
  • sendfile 将实在文件传给 socket。splice 用于在两个文件描述符间挪动数据,零拷贝,用于 socket 和管道之间相互定向。tee 用于两个管道之间复制数据。
  • IO 处理单元是一个专门的接入服务器,它实现负载平衡。申请队列是零碎外部各单元之间通信形式的形象,个别实现为池。
  • 阻塞和非阻塞是对文件描述符而言的。非阻塞 IO 个别和 IO 告诉机制一起应用,如 IO 复用或 SIGIO 信号。IO 复用自身是阻塞的,提高效率是因为同时监听多个事件。
  • 同步就是协同步调,按预约的先后秩序进行运行。解决客户连贯就是读写描述符,就是 IO,所以 IO 单元被定义为接入服务器。
  • 并发不适用于计算密集型,因为工作切换会升高效率,实用于 IO 密集型,如常常读写文件、拜访数据库。
  • 池就是事后动态分配资源,到时能够疾速应用。防止了对内核的频繁拜访。晋升性能办法:池、防止数据复制、上下文切换【线程数大于 cpu 数时】和锁。
  • 读写锁能够缩小锁的粒度实用于读多写少的状况。
  • epoll 须要应用一个额定的描述符保护事件表。EPOLLONESHOT 确保只有一个线程解决某个 socket。
  • sigaction 构造体中的 sa_mask 设置信号掩码,确切的说是在过程原有信号掩码的根底上减少信号掩码,以指定哪些信号不能发送给本过程。
  • sigset_t 每个元素的每个位示意一个信号,所以雷同的信号只能示意一次。
  • 子过程有和父过程雷同的信号掩码,但挂起信号集【发送然而被阻塞的信号】为空,就是说阻塞的信号是不可能发给子过程的。
  • 应用程序应用信号集 sigset_t 前,应调用 sigemptyset 或 sigfillset 一次,否则信号集初始状态不分明。
  • 最小工夫堆能够达到定时器的成果。
  • waitpid 用 NOHANG 就是非阻塞的了。socketpair 创立全双工管道的零碎调用。
  • 对信号量的操作成为 P(传递,进入临界区)V(开释,退出临界区)。最简略的二进制信号量,只有 0 和 1. 用一个一般变量模仿是不行的,因为检测和减 1 无奈原子实现。
  • linux 上的线程应用 clone 零碎调用创立的过程模仿的。
  • 目前能够实现跨过程的线程同步
  • 被 pthread_cancel 的线程能够决定是否容许被勾销以及如何勾销。
  • 销毁一个曾经加锁的互斥量将导致不可知的结果。互斥量属性设置中能够设置跨过程共享互斥量。pthread_mutexattr_setpshared()
  • 加锁 -》pthread_cond_wait 暗含解锁,确保能检测到条件变量的任何变动。
  • 有些函数不可重入次要是因为外部应用了动态变量。
  • 多线程程序中的一个线程调用 fork,只复制调 fork 的那个线程。互斥量的状态也继承,此时容易呈现死锁。
  • 所有线程共享信号处理函数,共享过程的信号。所以须要专门线程解决所有信号。
  • 过程池:典型的是 3 -10 个。线程池中的线程数量应该和 cpu 数量差不多。通信【通信:传递数据】父子过程间能够应用管道,多线程间应用一个全局数据即可。
  • pthread_create 当线程函数是类的成员函数时,必须为动态函数【确保没对象时也能够应用】,因为动态成员函数只能拜访动态成员,要拜访动静成员须要函数外部用单例或将类的对象作为参数传给函数。
  • SA_RESTART 被信号中断的零碎调用再信号处理完结后继续执行。
  • 将线程池或过程池中个数缩小为 1,便于调试逻辑。而后逐渐减少数量,看同步。
  • 过程类 [i].fd 通过给不同 i 的 fd 传递数据,调用不同的过程工作。m_sub_process[i].pid=fork()【fork 了 maxnum 次】。
  • 线程池:线程函数一起都启动,启动后进入 while(!stop) 循环,一直的锁队列,取工作。

POSIX 线程

  • 只有互斥量的客人可能解锁它。
  • 线程的堆栈受限。
  • 线程完结形式要么从线程函数 return,要么调用 pthread_exit,进入终止态,直到被拆散或被连贯。创立不须要连贯的线程应该应用 detachstate 属性建设线程使其主动拆散。
  • pthread_join 会阻塞调用者,直到被 join 的线程完结,join 返回被连贯的线程也拆散,所以只能被 join 一次,下一次就谬误了。
  • 应用条件变量时必须保障如果有线程期待,则该线程期待后必然会收到信号(if/while)
  • 条件变量能够使线程处于期待状态而不耗费资源。条件变量必须跟一个互斥变量一起应用,因为条件变量就是共享的全局数据??【条件和锁联合独特爱护共享数据】status = pthread_cond_wait(&alarm_cond, &alarm_mutex);
  • 没有条件变量,程序员可用应用轮询某个变量来实现停等 - 告诉同步,然而十分耗费系统资源。
  • 如果确定线程不须要被 Join, 则申明为 Detached 能够节俭系统资源
  • pthread_self 取得本身的 ID,只能通过 ID 操作线程。main 是主线程,主线程进行所有线程也进行,main 中调用 pthread_exit,这样过程就必须期待所有线程完结能力终止。
  • 通过向 pthread_t(ID)=pthread_create 传递线程函数地址和函数参数来创立线程。留神以后线程从 pthread_create 返回前,新创建的线程可能曾经运行结束了。
  • 舀水桶相似一个互斥量:桶用来爱护“舀水”临界区【拜访临界资源(共享数据?)的那段程序是临界区】。或者将桶了解为:用来确保一次只能由一个人舀水的不变量。
  • 在访问共享数据的代码段四周加锁互斥量,则一次只能有一个线程进入该代码段。
  • pthread_mutex_t 示意互斥量,不能拷贝,能够拷贝指针。
  • 当调用 pthread_mutex_lock 时,如果互斥量曾经被锁住,线程将被阻塞。调用 pthread_mutex_trylock 时不会阻塞,会返回 EBASY,能够做其余的事件去。
  • 互斥量的实质是串行执行。
  • 解决死锁的两种办法:一,规定加锁程序;二,trylock 如果不行回退,解锁所有已加锁的互斥量
  • sched_yield() 将处理器交给另一个期待解决的线程,如果没有期待解决的线程。立刻返回。sleep() 能够确保其余线程有机会运行。
  • 依照相同的程序解锁,有助于缩小线程做回退操作的可能。因为同一个线程函数中加锁程序是一样的。对于不同的线程函数程序应该不重要
  • 线程运行于解锁和阻塞之间时,其余线程能力扭转共享数据状态。此时共享状态的扭转,本线程是无奈晓得的。-> 须要条件变量。队列满,队列空,满空就是条件变量。
  • 动静初始化的条件变量须要 pthread_cond_destroy 来开释。动态初始化的不用开释。开释前确保其余线程不应用他。
  • 在阻塞线程之前,条件变量期待操作 pthread_cond_wait 将解锁互斥量,从新返回线程之前,会再次锁住互斥量。子线程只在 pthread_cond_wait 期待的短时间内能够加锁,批改共享数据,而后解锁。
  • pthread_cond_timedwait 的意思就是我在这里等 time 工夫,如果工夫内条件变量变了,或者不变,我都要跳出 while(谓词)的循环,按状况解决。
  • pthread_cond_wait 和 pthread_cond_signal 必须同时产生能力胜利。
  • 互斥量:条件变量是 一对多的关系
  • 当线程调用 pthread_create 时,她所能看到的内存值也是它建设的线程能看到的,之后的线程不肯定能看到。
  • 线程解锁互斥量时所看到的的数据,也能被起初间接锁住雷同互斥量的线程看到。解锁后写入的数据,不用被其余线程看见(因为那不是用来同步的数据,没必要所有人看见,同步就应该加锁)。
  • 线程终止,勾销,从启动函数返回,pthread_exit 时看到的数据,可能被连贯该线程的其余线程看到。终止后写入的数据不会被看到。
  • 线程发信号或播送时看到的内存数据,能够被唤醒线程看到。之后写入的不会。
  • 线程调配的堆栈和堆空间是公有的,除非传给其余线程指针。register(寄存器变量)和 auto 变量(大部分变量默认 auto)(static 变量的生命期长)中的数据可随时读取,像在同步程序中一样
  • 两个处理器将各自的高速缓存中的数据写入主存的程序是不肯定的,即便写到相应高速缓存的程序有先后之分。同一线程写数据也未必依照程序刷新进内存,这使得其余线程读取后果不对。
  • 锁住互斥量 -> 内存屏障 -> 内存屏障 -> 解锁互斥量
  • 应用线程的形式:流水线、工作组(工作线程在数据的不同局部操作)、C/S。
  • pthread_attr_setdetachstate (&_attr, PTHREAD_CREATE_DETACHED); 阐明在创立线程后,咱们不在须要应用线程 ID。
  • 不变量(Invariant):程序所做的一些假如,特地是指变量之间的关系。断定条件(Predicates):形容不变量状态的逻辑表达式。
  • pthread_kill(thdid, SIGTERM) 给特定线程发信号
正文完
 0