Unix/Linux程序设计
文章平均质量分 91
主要记录了Unix/Linux下对文件、内存、多任务、进程间通信以及网络编程的知识点。用最简单的实例帮助你了解Unix/Linux下开发的各种机制。希望能和大家一起交流。
lycclsltt
这个作者很懒,什么都没留下…
展开
-
几种服务器模型
TCP测试用客户程序每次运行客户程序,在命令行参数指定服务器的ip地址,端口,发起连接的子进程数,和一个待发送的字符串数据,客户程序将模拟多个客户根据指定的子进程数创建子进程来并发的连接到服务器,并发送数据,服务器收到数据后都原样的回发给客户,是一点典型的回射服务器。#include "net.h"char *addr = NULL;char *request = NULL;...原创 2014-08-30 20:37:29 · 2799 阅读 · 0 评论 -
udp套接字使用信号驱动式I/O
信号驱动式I/O的本质就是:进程预先告知内核当某个描述符发生事件时,内核会向该进程发送SIGIO信号通知进程,进程可在信号处理函数中进行处理进程可以通过fcntl打开O_ASYNC标志或ioctl打开FIOASYNC标志来通知内核,二者的区别是一些系统不支持fcntl,所以应尽量使用ioctl对于TCP套接字产生SIGIO信号的条件:1.监听套接字上有新连接请求完成原创 2014-07-22 20:00:26 · 2288 阅读 · 0 评论 -
SO_REUSEADDR 套接字选项应用实例
网络上关于SO_REUSEADDR套接字选项用来解决地址重用问题的资料不少,但只停留在文字表达上,并没有实例,很容易误导初学者,并产生疑惑,此处不再赘述。下面通过一个简短的例子来展示如何在项目中合理的使用该选项,以及需要注意的问题。关于TCP断开连接四次握手,如图所示应用场景:之前项目中遇到一个问题,聊天服务器的开启,关闭和重启,例如将服务器原创 2014-07-08 00:33:48 · 3164 阅读 · 0 评论 -
心跳机制详解
应用场景:在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活什么是心跳机制?就是每隔几分钟发送一个固定信息给服务端,服务端收到后回复一个固定信息如果服务端几分钟内没有...原创 2014-07-06 12:31:15 · 26112 阅读 · 1 评论 -
用udp实现广播通信
特点:1.数据传输不用建立连接,所以不可靠(符合udp协议的特点)2.数据的发送是面向整个子网的,任何一台在子网内的计算机都可以接收到相同的数据;3.广播用于udp和原始IP,不能用于TCP用途:1.定位本地子网内的主机前提是已知该主机位于本地子网,但是不知到他的单播地址。例如通过广播向所有子网内的主机的某端口发送数据报,如果主机有进程在该端口等待接收数据并回射数据,那原创 2014-06-25 16:25:12 · 12136 阅读 · 1 评论 -
setjmp与longjmp
在C中有时我们会使用goto语句用于执行跳转,但是不能跨越函数#include void func2(){ int num = 0;dst2: if (num > 0) { printf("func1()\n"); func3(); } if (num == 1) return; num++; goto dst2;}void func3(){}原创 2014-06-18 22:40:36 · 1051 阅读 · 0 评论 -
非阻塞connect
一、用途:1.提高程序效率默认情况下connect函数是阻塞的,它发起TCP连接的三路握手。完成一个connect需要花费一个RTT时间(从本地主机到对端再回到本地),RTT的波动范围很大,局域网上几毫秒到几百毫秒,广域网上甚至能需要几秒,这对计算机来说是非常漫长的时间,这段时间可以用来执行其他的处理工作,提高效率。因此非阻塞的connect函数是必要的。2.同时建立多个连接,不必原创 2014-06-07 10:47:44 · 1445 阅读 · 0 评论 -
ioctl获取网络接口信息
linux下网络程序经常在启动执行后使用ioctl获取主机的全部网络接口信息,例如接口地址、是否支持广播,是否支持多播等。函数原型#include int ioctl(int d, int request, ...);返回值:成功返回0,出错返回-1 常见选项SIOCGIFCONF 获取所有接口的列表SIOCGIFBRDADDR 获取广播地址S原创 2014-06-09 23:26:39 · 3003 阅读 · 0 评论 -
MSG_PEEK标志
MSG_PEEK标志可以用来读取套接字接收队列中可读的数据,一些情况会用到它,比如为了避免不阻塞而先检查套接字接收队列中可读的数据长度,再采取相应操作。当然,不阻塞也可采取其他的方法,例如非阻塞式I/O。MSG_PEEK标志会将套接字接收队列中的可读的数据拷贝到缓冲区,但不会使套接子接收队列中的数据减少,常见的是:例如调用recv或read后,导致套接字接收队列中的数据被读取后而减少,原创 2014-06-06 21:34:29 · 8132 阅读 · 0 评论 -
套接字设置超时总结
涉及套接字I/O操作上设置超时的方法:1.调用alarm原创 2014-05-06 12:34:04 · 2981 阅读 · 0 评论 -
创建守护进程
在linux或者unix操作系统中在系统的引导的时候会开启很多服务,这些服务就叫做守护进程。守护进程是在后台运行不与任何控制终端关联,是Linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。大多数服务都是通过守护进程实现的。它从被执行开始运转,直到整个系统关闭时才退出。如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就原创 2014-05-02 15:03:13 · 1193 阅读 · 0 评论 -
socket抓取网页
#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;void func(){ string url; cout << "输原创 2014-04-29 10:58:58 · 1409 阅读 · 0 评论 -
UDP中使用connect函数
先看一个例子,下面是一个采用UDP协议的客户程序,调用sendto向服务器端发送数据,而服务器并不启动,sendto返回,表示套接字缓冲区中有可用空间,程序会阻塞在recvfrom。net.h #ifndef MY_NET_H #define MY_NET_H #include #include #原创 2014-04-24 12:34:30 · 2533 阅读 · 1 评论 -
I/O复用模型之poll
poll提供的功能与select类似,poll效率高。原型:#include int poll(struct pollfd *fds, nfds_t nfds, int timeout); 返回值:若有就绪描述符则为其数目,超时则为0,出错为-1参数:nfds:struct pollfd数组中元素的个数timeout:指定poll函数返回前等待的毫秒数IN原创 2014-04-19 15:02:04 · 1186 阅读 · 0 评论 -
shutdown函数
发送一行文本给服务器,然后等待应答,这就形成了一个简单的回射服务器。如果把客户和服务器之间的网络作为全双工管道考虑,请求从客户向服务器发送,应答从服务器回发给客户。下图展示了客户与服务器之间的数据分组,忽略网络中的TCP确认(ACK)。原创 2014-04-18 20:25:35 · 1950 阅读 · 0 评论 -
I/O复用模型之select
在编程中我们用到最多的是阻塞式I/O模型。例如,进程调用recvfrom,它直到数据报到达后从内核缓冲区复制到进程缓冲区才返回。若没有数据报到达,或者没有复制到进程缓冲区,recvfrom将一直阻塞。也有可能被信号中断,而返回。例如进程调用fgets,直到用户输入回车后才后返回。否则将一直阻塞。而I/O复用模型在一定程度上可以解决这样的问题。什么是I/O复用呢?编程时要同时处理多个原创 2014-04-18 17:36:31 · 1564 阅读 · 0 评论 -
fork()后父子进程共享文件
fork函数的特点概括起来就是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。fork的另一个特性是所有由父进程打开的描述符都被复制到子进程中。父、子进程中相同编号的文件描述符在内核中指向同一个file结构体,也就是说,file结构体的引用计数要增加。下面展示了一个返回本地时间给客户的简单客户-服务器模型,其中服务端为了并发处理来自客户的请求会调用fork创建原创 2014-04-10 11:04:18 · 1946 阅读 · 0 评论 -
网络IPC之字节序
运行在一台计算机上的进程相互通信时,一般不考虑字节序顺序。字节序是一个处理器架构特性,用于指示像整数这样的大数据类型内部字节顺序。大端字节序,最大字节地址对应数字最低字节小端字节序,最小字节地址对应最低字节例如:整数2139127808的二进制表示为0111111110000000100000000000000001111111100000001000000000000原创 2014-03-13 11:12:40 · 1277 阅读 · 0 评论 -
linux进程间通信之信号量
信号量是一种用于提供不同进程间或一个给定进程的不同线程间同步的手段。它是一个计数器,用于多进程对共享数据的访问。为获取共享资源,进程要执行下列操作:1)测试控制该资源的信号量2)若值为正,则进程可以使用资源,信号量值-1,表示它使用了一个资源单位。 当进程不再使用资源时,信号量值+1,如果有进程正在休眠等待此信号量,则唤醒它们。3)若值为0,则进程休眠,直至值大于0。进原创 2014-03-12 17:01:41 · 1397 阅读 · 0 评论 -
linux进程间通信之消息队列
消息队列是消息的链表,存放在内核中并由消息队列标识符标识。对于系统中的每个消息队列,内核维护一个定义在头文件中的信息结构struct msqid_ds { struct ipc_perm msg_perm; /* 相关权限 */ time_t msg_stime; /* 上一次发送时间 */ time_t msg原创 2014-03-11 10:18:57 · 1629 阅读 · 2 评论 -
linux进程间通信之共享内存
共享存储允许两个或多个进程共享同一给定的存储区。因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC。使用共享存储时要注意多个进程之间对同一给定存储区的同步访问.内核为每个共享存储段设置了一个shmid_ds结构struct shmid_ds{ struct ipc_perm shm_perm; /*操作权限*/ int shm原创 2014-03-10 13:58:48 · 1320 阅读 · 0 评论 -
linux进程间通信之实名管道
pipe函数建立的管道实际上是个匿名管道,由内核负责维护的一块存储区域。半双工通信,而且只能用于共同祖先进程之间。通过FIFO,不相关的进程也能交换数据。FIFO实际上是一种文件类型,打开的描述符号可以读写(two-way双工)。#include #include int mkfifo(const char *pathname, mode_t mode);返回值: 成功返回0原创 2014-03-09 11:34:07 · 1839 阅读 · 0 评论 -
brk/sbrk工作原理
malloc是c中常用的内存操作函数,malloc动态的申请一块指定大小的内存,方便存放数据c++中的new实际上除了malloc分配内存之外还会调用构造函数初始化数据而brk/sbrk则是实现malloc的底层函数,其中brk是系统调用。操作起来更为灵活,但很多人往往不容易理解。#include int brk(void *addr);void *sbrk(i原创 2014-03-08 22:30:09 · 3174 阅读 · 2 评论 -
linux进程间通信之匿名管道
管道是UNIX系统IPC最古老的形式,并且所有UNIX系统都提供此种通信机制。管道有下面两种局限性。1.历史上,它们是半双工的,数据只能在一个方向上流动2只能在公共祖先的进程之间使用。例如,父子进程之间就可应用管道。尽管有这两种局限性,半双工管道仍是最常用的IPC形式管道是用pipe函数创建的#include int pipe(int pipefd[2]);原创 2014-03-08 13:06:49 · 1303 阅读 · 0 评论 -
stat、fstat和lstat函数
#include #include #include int stat(const char *path, struct stat *buf);int fstat(int fd, struct stat *buf);int lstat(const char *path, struct stat *buf);三个函数的返回值:若成功则返回0,若出错则返回-1s原创 2014-03-07 16:31:32 · 2623 阅读 · 0 评论 -
dup和dup2函数
下面两个函数可以用来复制一个现存的文件描述符#include int dup(int oldfd);int dup2(int oldfd, int newfd);由dup返回的新文件描述符一定是当前可用文件描述符的最小值,用dup2则可以用newfd参数指定新描述符的值。如果newfd已经打开,则先将其关闭。如若oldfd等于newfd则dup2返回newfd,而不原创 2014-03-07 14:27:23 · 1207 阅读 · 0 评论 -
wait和waitpid函数
#include pid_t wait(int *status);pid_t waitpid(pid_t pid, int *status, int options);两个函数的参数statloc是一个整形指针。用来存放终止状态,如果不关心终止状态,可设为NULL如果所有子进程都还在运行,则阻塞如果一个子进程终止,则缺德该子进程的终止状态立即返回如果没有原创 2014-03-06 10:59:37 · 1141 阅读 · 0 评论 -
linux目录操作
获取当前路径#include char *getcwd(char *buf, size_t size);char *getwd(char *buf);char *get_current_dir_name(void);这些函数都返回程序到当前工作路径get_current_dir_name() 将通过malloc申请一段足够大的空间来存放当前路径。getwd()原创 2014-03-05 17:36:54 · 939 阅读 · 0 评论 -
linux下获取系统环境变量
在c,main函数的前两个参数argc, argv被很多人熟悉,但main函数还有第三个参数------arge。main的第三个参数里存的是系统变量,所以可以通过这个参数获得系统环境变量#include int main(int argc, char** argv, char** arge){ while(*arge) { printf("%s\n", *arge++)原创 2014-03-05 15:41:09 · 2095 阅读 · 0 评论 -
linux线程同步之读写锁
读写锁实际是实现保护共享资源而提出一种锁机制。 它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑CPU数。写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。原创 2014-02-26 15:02:34 · 1362 阅读 · 1 评论 -
linux线程同步之信号量
初始化信号量 int sem_init(sem_t *sem, int pshared, unsigned int value);sem_init() 初始化一个定位在 sem 的匿名信号量。value 参数指定信号量的初始值。 pshared 参数指明信号量是由进程内线程共享,还是由进程之间共享。如果 pshared 的值为 0,那么信号量将被进程内的线程共享,并且应该放置原创 2014-02-26 14:14:15 · 1258 阅读 · 0 评论 -
linux多线程实现黑客帝国字符滑屏效果
利用curses库来实现字符界面的改变,利用多线程实现每个字符的改变设计思想:以整个屏幕为背景,随机生成26个字母以及每个字母初始的x,y值以及speed速度值,通过改变字符的y值,清屏并重绘,来实现字符的滑屏效果最初线程设计思想:创建26个线程,每个线程控制一个字母,线程函数中根据y值清屏并重绘字符,对重绘过程采用互斥量加锁,由于清屏操作也会涉及到线程同步,故实现较为麻烦。原创 2014-02-25 21:37:20 · 1925 阅读 · 0 评论 -
linux线程同步之条件变量
条件变量是线程可用的另一种同步机制。条件变量给多个线程提供了一个会合的场所。条件本身是由互斥量保护的。线程在改变 条件状态前必须首先锁住互斥量。条件变量的初始化 pthread_cond_init去除初始化 pthread_cond_destroy等待 pthread_cond_wait满足条件给向进程发送信号 pthread_cond_signal下面程序展示原创 2014-02-25 12:26:16 · 991 阅读 · 1 评论 -
linux线程同步之信号
linux中向某个线程发送信号,若没有对该信号的处理函数,则会导致程序结束。如下面的程序,创建一个线程,主线程向其发送一个信号,会导致程序立即结束#include #include pthread_t t;void* run(void* arg){ while(1) { printf("Hello\n"); }}main(){ pthread_cre原创 2014-02-25 11:21:40 · 1164 阅读 · 0 评论 -
linux线程同步之互斥锁
当程序中存在多个线程时,如果每个线程使用的变量都是其他线程不会读取或修改的,那么就不存在一致性问题。如果变量是只读的,多个线程访问也不会有不一致问题。但是,当某个线程可以修改变量,而其他线程也可以读取或修改该变量时,为了确保数据存储时不会访问到无效的值,为了避免脏数据,就需要对这些线程进行同步。该程序中每个线程分别对共享变量进行+1并且比较,体现了多线程访问共享资源时读写造成的原创 2014-02-24 21:13:25 · 1023 阅读 · 0 评论