
Linux
文章平均质量分 64
Joker......
这个作者很懒,什么都没留下…
展开
-
TCP多线程
服务器实现同时为多客户服务使用TCP举例,有关基于UDP为多客户服务的服务器多线程实现原理代码演示server#define PORT 6666#define IP "192.168.175.130"void print_err(char *str, int line, int err_no){ printf("%d, %s: %s\n", line, str, strerror(err_no)); exit(EXIT_FAILURE);}void sign_原创 2022-04-09 18:14:25 · 2993 阅读 · 0 评论 -
域套接字.
使用套接字实现本机进程间通信为本机进程间通信而生——域套接字实现方法第一种:使用网络套接字 比如使用TCP/IP协议族来实现,不管是使用TCP还是使用UDP都可以,只要目标ip指定为本机IP或者127.0.0.1网环地址,即可实现本机进程间通信。 事实上使用实现网络通信的“网络套接字”来实现本机进程间通信,有点大才小用,如果想要使用套接字来实现本机进程间通信的话,我们应该是使用“域套接字”,而不是“网络套接字”。 实现本机进程间通信,“域套接字”的效率高于“网络套接字”。 第二种原创 2022-04-08 16:51:42 · 3591 阅读 · 0 评论 -
网络编程UDP
UDP通信UDP是User Datagram Protocol 的缩写,直译为用户数据报协议。UDP的特点UDP是不可靠传输协议 刚好与TCP相反,它是一种面向无连接的不可靠传输层协议,而且UDP每次发送的分组数据大小都是固定的 为什么UDP是不可靠传输? 不建立连接 没有应答机制 不会根据网络的好坏调整分组数据的大小 其实有关UDP为什么是不可靠传输协议,主要是它没有连接和应答机制,导致UDP在发送数据时,根本不清楚通信线路的连接状态,所以UDP传输数据时,无法原创 2022-04-07 19:05:16 · 1530 阅读 · 0 评论 -
网络编程TCP
实现TCP服务器程序第一步:调用socket 网络API,创建套接字文件socket函数 int socket(int domain, int type, int protocol); 功能:创建一个套接字文件,然后文件形式来操作通信,不过套接字文件没有文件名。 Linux有7种文件,套接字文件就是其中一种。 socket翻译为中文就是“套接字”的意思,其实翻译为插座更合适些,因为socket本来就有插座的意思。 使用socket创建一个通信的套接字文件,就好比如插上了一个通信原创 2022-04-06 17:41:27 · 519 阅读 · 0 评论 -
存储映射(二)——mmap函数
内存映射映射时,具体映射到了进程空间的什么位置呢?映射到了“进程应用空间”堆和栈中间那片虚拟地址的位置。进程内核空间:用于映射“OS”所在的物理内存空间。 进程应用空间:用于映射“应用程序”所在的物理内存空间。zmmap函数函数原型 #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 功能 将文件所在磁盘空间原创 2022-04-01 14:03:02 · 508 阅读 · 0 评论 -
存储映射(一)
存储映射普通读写文件方式的缺点使用文件IO的read、write来进行文件的普通读写时,函数经过层层的调用后,才能够最终操作到文件,比如我们可以读效率低(read函数)为例:应用层 read(fd, buf, sizeof(buf)); //buf应用缓存-------------------|------------------------------------------OS层 |xxx1_read(**, xxx1_buf, **); //xxx_buf1内存缓冲原创 2022-03-31 23:22:12 · 1028 阅读 · 1 评论 -
linux异步IO
异步IO回顾同时读键盘、鼠标的方法多进程 多线程 将“读鼠标”和“读键盘”设置为非阻塞 多路IO(select、poll机制) 异步IO异步IO的原理前面四种方式都是主动去读,对于read函数来说它并不知道是不是一定有数据,如果有数据就读到数据,没有数据要么阻塞直到读到数据为止,要么不阻塞。这就好比我想去澡堂洗澡,我不知道有没有位置,我去了后如果有位置我就立即洗澡(立即读数据),如果没有位置要么等(阻塞读),要么离开过段时间再来看(非阻塞读)。实际上除了以上描述符的方式外,还有原创 2022-03-31 20:29:50 · 629 阅读 · 0 评论 -
多路IO(三)——poll机制
多路IO之poll机制poll函数1.函数原型#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);2.功能监听集合有没有动静,如果没有动静就阻塞 如果有动静就成功返回,返回值为集合中有动静的fd的数量3.参数fds:这个参数写为struct pollfd fds[]更好理解些,第一个参数要求传递一个struct pollfd结构体数组。 这个数组就相当于select原创 2022-03-31 13:34:07 · 988 阅读 · 0 评论 -
多路IO(二)——select函数
代码演示:select每次重新监听时需要重新设置“集合”和“超时时间”,因为每次select监听结束时会清空“集合”和“超时时间”。int main(int argc, char *argv[]){ int ret = 0; int mousefd = 0; fd_set readfds; char buf[100] = {0}; char buf1; struct timeval timeover; mousefd = open("/dev/input/mouse0", O原创 2022-03-30 20:35:38 · 303 阅读 · 0 评论 -
多路IO(一)——IO多路复用
IO多路复用如何解决同时“读鼠标”和“读键盘”的问题多进程实现 多线程 将“读鼠标”和“读键盘”设置为非阻塞实现 多路IO有关多路IO多路IO的工作原理使用多路IO时,不需要多进程、多线程以“多线任务”方式实现,也不需要用到非阻塞,那么多路IO的实现原理又是什么? 我们以阻塞读为例,来讲解多路IO的原理。 图:如果是阻塞写的话,需要将文件描述符加入写集合,不过我们说过对于99%情况,写操作不会阻塞,所以一般情况下对于写来说,使用多路IO没意义。注意:对于多路IO来说,只有操原创 2022-03-29 22:26:59 · 875 阅读 · 0 评论 -
文件锁(四)——flock函数
flock函数使用flock函数来实现文件锁flock与fcntl所实现的文件锁一样,既能够用在多进程上,也能用在多线程上,而且使用起来比fcntl的实现方式更方便,只是使用这个函数时,需要注意一些小细节。flock函数函数原型 int flock(int fd, int operation); 头文件 #include <sys/file.h> 功能 按照operation的要求,对fd所指向的文件加对应的文件锁。 加锁不成功时会阻塞。 返回值成功0,原创 2022-03-29 14:16:24 · 3608 阅读 · 2 评论 -
文件锁(三)——文件锁的原理
文件锁的原理理解了文件锁的原理后,就可以理解为什么文件锁可以实现互斥与共享了。若A进程与B进程同时打开同一个文件,他们使用同一个文件表,使用同一个V节点,V节点指向hello这个文件,里面有一个锁链表,里面记录了锁的信息。加锁时,进程会检查共享的文件锁链表如果链表上只有读锁节点 所有目前其他进程对该文件只加了读锁,由于读锁时共享的,所以不管链表上有几个读节点,当前进程都能成功加读锁。 图: 提供:链表上可不可以存在n多个读锁节点? 答:可以,因为读锁是共享的,不管别的进程有没有原创 2022-03-28 23:04:35 · 1679 阅读 · 1 评论 -
文件锁(二)——文件锁的读锁和写锁
文件锁的读锁和写锁对文件加锁时可以加两种锁,分别是“读文件锁”和“写文件锁”,简称读锁和写锁。读锁、写锁之间关系读锁和读锁共享:可以重复加读锁,别人加了读锁在没有解锁之前,我依然可以加读锁,这就是共享。 读锁和写锁互斥:别人加了读锁没解锁前,加写锁会失败,反过来也是如此。 加锁失败后两种处理方式: 阻塞,直到别人解锁然后加锁成功为止。 出错返回,不阻塞 写锁与写锁互斥:别人加了写锁在没有解锁前,不能加写锁,加写锁会失败。 加锁失败后两种处理方式: 阻塞,直原创 2022-03-28 20:15:55 · 8194 阅读 · 0 评论 -
文件锁(一)——文件锁的概述
文件锁的概述文件锁也被称为记录锁,文件锁如果深耕的话,意义不大(比如文件锁起码分为了建议锁和强制性锁)。但是深入没有意义的,因为实际开发很少用上,文件锁用到的机会不多,那为什么要学?主要是为了对比学习各种的加锁机制,比如进程有进程信号量加锁机制,线程有线程互斥锁,线程信号量等加锁机制,学习文件锁有助于我们对比理解,对于我们后续理解驱动课程的内核锁,c++,java等库所提供的资源保护的锁机制,都是很有意义的。 另外还有一个目的,那就是练习fcntl函数的使用,因为文件锁也需要用到fcntl函数原创 2022-03-28 00:33:42 · 3611 阅读 · 2 评论 -
文件属性(四)——st_mode
st_modest_mode st_link st_uid st_gid st_size st_atime 文件名-rwxr-xr-x 1 root root 16168 Mar 26 08:27 a.out-:文件类型 rwxr-xr-x:文件权限 每三个一组 注意第三个:如果是-,表示不可以被CPU执行,如果是x,表示可以被执行。 三组权限大小 正常情况下,所属用户的操作权限>=组员用户的操作权限>=其他不想干用户的操作权限 这就相当于你的私人物品原创 2022-03-27 23:02:22 · 1553 阅读 · 0 评论 -
文件属性(三)——st_uid属性和st_gid属性
st_uid属性和st_gid属性st_mode st_link st_uid st_gid st_size st_atime 文件名drwxr-xr-x 2 root root 4096 Mar 27 01:31 IO其中不好理解的是st_mode、st_uid和st_gidst_uid和st_gid是什么? 用户ID(用户编号),编号是唯一的,例子中的编号代表的就是lzf这个用户。 在Linux下,是以编号形式来管理用户的,这有点像人名和身份证的关系。 文件属性中,为什么有s原创 2022-03-27 17:29:33 · 1167 阅读 · 0 评论 -
文件属性(二)——获取文件属性的函数:stat、lstat、fstat
获取文件属性的函数:stat、lstat、fstat这三个是兄弟函数,实现的功能相同,只是略微有区别,我们只要把stat函数搞清楚了,lstat,fstat非常容易理解。ls命令其实就是调用了这三个函数中的lstat来实现的,我们可以调用lstat函数来自己实现一个ls命令为什么要讲stat、lstat、fstat函数?将这三个函数,重点不是实现ls命令,而是通过这三个函数的学习,掌握用法,和理解文件的各种属性stat1.函数功能功能就是获取文件的属性信息每个文件的属性信息,原创 2022-03-27 12:24:45 · 1363 阅读 · 0 评论 -
文件属性(一)——文件的7种类型
文件的7种类型Linux一切皆文件,Linux文件一共分为7类分别是- d c s p l b。普通文件(regular file -)普通文件根据存放的内容的不同,又分为如下两种: 文本文件 存放的都是文字编码,文本编辑器打开后,会将这些文字编码翻译为文字图形,供人识别 纯二进制文件 比如经过编译后得到的可执行文件,里面放的是cpu执行的纯二进制机器码,由于文本编辑器只认识文字编码,所以用文本编辑器打开后,显示的内容无法是错乱的,无法识别的。 其实不管原创 2022-03-26 21:48:23 · 6195 阅读 · 1 评论 -
函数fcntl
函数fcntlfcntl函数可以改变已经打开文件的属性int fcntl(int fd, int cmd, ... /* arg */ );返回值:若成功,则依赖于cmd;若出错,返回-1功能fcntl函数其实是file control的缩写,可以通过fcntl设置、或者修改已打开文件的某些性质参数fd:指向打开文件 cmd:控制命令,通过指定不同的宏来修改fd所指向文件的性质。 F_DUPFD:Duplicating a file descriptor 复制文件描述符原创 2022-03-26 14:13:05 · 911 阅读 · 0 评论 -
Linux新增API:eventfd
Linux新增API:eventfd进程间等待通知机制eventfd APIint eventfd(unsigned int initval, int flags); 用来创建一个用于事件通知的eventfd对象 返回值为一个int型fd,用来引用打开的对象 打开的对象在内核中是一个64位无符号整型数据,初始化位initval 计数器数据类型:typedef uint64_t eventfd_t flags: EFD_CLOEXEC:类似于open的flags,fork子进原创 2022-03-23 23:35:51 · 220 阅读 · 0 评论 -
Linux新增API:timerfd
Linux新增API:timerfdtimerfd函数功能:通过文件I/O方式去获取定时器的通知事件 相关API: int timerfd_create(int clockid, int flags); int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value); int timerfd_gettime(int fd, struct iti原创 2022-03-23 18:38:41 · 475 阅读 · 0 评论 -
Linux新增API:signalfd
Linux新增API:signalfd信号通信机制小结优缺点在软件层次上是对信号中断机制的一种模拟 信号是进程间通信中唯一的“异步通信机制” 带来的弊端,数据的并发访问、可重入问题 解决方案:将信号抽象为文件,将信号转化为I/O文件操作signalfd 将信号抽象为一个文件描述符 将信号的异步处理转化为文件的I/O操作 当有信号发生时,可以对其read 每次read都会阻塞、直到signalfd指定的信号到来 也可以将信号的监听放到selec原创 2022-03-23 13:57:03 · 1618 阅读 · 0 评论 -
6.11 通过文件描述符来获取信号
6.11 通过文件描述符来获取信号从内核2.6.22版本开始,Linux提供了另外一种机制来接收信号:通过文件描述符来获取信号即signalfd机制。这个机制和sigwaitinfo非常地类似,都属于同步等待信号的范畴,都需要首先调用sigprocmask将关注的信号屏蔽,以防止被信号处理函数劫走。不同之处在于,文件描述符方法提供了文件系统的接口,可以通过select、poll和epoll来监控这些文件描述符。signalfd接口的定义如下:int signalfd(int fd, co原创 2022-03-23 12:49:47 · 1682 阅读 · 0 评论 -
4.8 exec家族
该系统调用的作用是,将新程序加载到进程的地址空间,丢弃旧有的程序,进程的栈、数据段、堆栈等会被新程序替换。 基于execve系统调用的6个exec函数,接口虽然各异,实现的功能却是相同的,首先我们来讲述与 系统调用同名的execve函数。...原创 2022-03-22 23:19:48 · 126 阅读 · 0 评论 -
6.10.1 pause函数
6.10.1 pause函数pause函数将调用线程挂起,使进程进入可中断的睡眠状态,直到传递了一个信号为止。这个信号的动作或者是执行用户定义的信号处理函数,或者是终止进程。如果是执行用户自定义的信号处理函数,那么pause会在信号处理函数执行完毕后返回;如果是终止进程,pause函数就不返回了。如果内核发出的信号被忽略,那么进程就不会被唤醒。pause函数的定义如下:int pause (void);比较有意思的是,pause函数如果可以返回,那它总是返回-1,并且errn原创 2022-03-22 23:06:08 · 1530 阅读 · 0 评论 -
6.8.3 sigqueue函数
6.8.3 sigqueue函数在信号发送的方式当中,sigqueue算是后起之秀,传统的信号多用signal/kill这两个函数搭配,完成信号处理函数的安装和信号的发送。后来因为signal函数的表达力有限,控制不够精准,所以引入了sigaction函数来负责信号的安装与其对应的是,引入了sigqueue函数来完成实时信号的发送。当然了,sigqueue函数也能发送非实时信号。sigqueue函数的接口定义如下:int sigqueue(pid_t pid, int sig, co原创 2022-03-22 21:22:48 · 1586 阅读 · 0 评论 -
6.8.2 raise函数
6.8.2 raise函数 Linux提供了向进程自身发送信号的接口:raise函数,其定义如下: int raise(int sig); 这个接口对于单线程的程序而言,就相当于执行如下语句: kill(getpid(),sig) 这个接口对于多线程的程序而言,就相当于执行如下语句: pthread_kill(pthread_self(),sig) 执行成功的时候,返回0,否则返回非零的值,并置errno。如果sig的值是无效的,raise函数就将 errno置为原创 2022-03-22 18:01:13 · 769 阅读 · 0 评论 -
6.8.1 kill、tkill和tgkill
6.8.1 kill、tkill和tgkillkill函数的接口定义如下:int kill(pid_t pid, int sig);注意,不能望文生义,将kill函数的作用理解为杀死进程。kill函数的作用是发送信号。kill函数不仅可以向特定进程发送信号,也可以向特定进程组发送信号。第一个参数pid的值,决定了kill函数的不同含义,具体来讲,可以分成以下几种情况。 pid>0:发送信号给进程ID等于pid的进程。 pid=0:发送信号给调用进程所在的同一个进程组的原创 2022-03-22 17:58:32 · 3178 阅读 · 0 评论 -
6.7 信号的安装
6.7 信号的安装前面讲了传统信号的很多弊端,讲了signal的兼容性问题,有问题就会有解决方案。对此,Linux提供了新的信号安装方法:sigaction函数。和signal函数相比,这个函数的优点在于语义明确,可以提供更精确的控制。先来看一下sigaction函数的定义:int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); struct sigaction { voi原创 2022-03-22 17:10:28 · 1300 阅读 · 0 评论 -
6.1 信号
第6章 信号信号是一种软件中断,用来处理异步事件。内核递送这些异步事件到某个进程,告诉进程某个特殊事件发生了。这些异步事件,可能来自硬件,比如访问了非法的内存地址,或者除以0了;可能来自用户的输入,比如shell终端上用户在键盘上敲击了Ctrl+C;还可能来自另一个进程,甚至有些来自进程自身。信号的本质是一种进程间的通信,一个进程向另一个进程发送信号,内核至少传递了信号值这个字段。实际上,通信的内容不止是信号值。**信号机制是Unix家族里一个古老的通信机制。**传统的信号机制有一些弊端,更为严原创 2022-03-21 21:13:20 · 414 阅读 · 0 评论 -
进程间通信(二十三)——信号底层API:sigaction
信号底层API:sigactionlinux中信号的分类标准信号及其不可靠性标准信号 1-31号信号,也叫不可靠信号,继承UNIX信号,采用位图管理 如果同时来相同的信号来不及处理,内核会丢弃掉 实时信号 32~64号信号,是可靠的,采用队列管理 来一次,处理一次,转发一次 信号处理机制内核对信号的处理A进程向B进程发送一个信号,内核会首先收到信号,然后发给B进程,在发送给B进程之前,内核负责管理这些信号 对于不可靠信号,内核采用位图标记,给该信号分配sigque原创 2022-03-21 19:53:23 · 1449 阅读 · 0 评论 -
进程间通信(二十二)——信号处理函数
信号处理函数信号的本质是一种软中断,中断有优先级,信号也有优先级 信号处理函数类似于中断处理函数 信号也可以随时打断当前正在运行的程序,去运行信号处理函数编程要点 重入:可能在任何时刻、任意地点打断当前进程的执行 尽量不要在处理函数中修改全局数据 尽量使用可重入函数,被打断的进程可能正在调用不可重入函数 难点:很难写出一个安全地、可重入的信号处理函数 int sum; int add(int count) { static int sum原创 2022-03-21 13:15:10 · 514 阅读 · 0 评论 -
进程间通信(二十一)——信号机制:signal
信号机制:signal信号的基本概念信号(signal)又叫:软中断信号,是一种异步通信的IPC 类似于硬件中断,可以将一个事件以信号形式通知给进程 给一个指定的进程发送一个信号量 信号只是告诉进程发送了什么事,并不传递数据 进程表的表项中有一个软中断信号域,有信号发给该进程,对应位置位 进程根据接收信号类型作相应的处理 信号的来源来自shell终端用户输入的各种信号:ctrl + C/D 来自其他进程或者进程本身发送的信号 来自系统内部的信号 硬件异常:如SIGBU原创 2022-03-21 12:10:55 · 1018 阅读 · 0 评论 -
进程间通信(二十)——文件锁
文件锁优点在所有的IPC通信中效率最高缺点所有共享内存带来的问题:同步 解决方法 System V信号量 POSIX信号量 文件锁 专门为文件设计的同步技术 适用于操作共享文件映射 文件锁什么是文件锁英文名:file lock,在同一时刻只允许一个进程对文件进行访问 建议性锁:advisory locking,又称协调锁 内核只提供加减锁以及检测是否加锁,不提供锁的控制与协调工作 需要多进程相互检测确认的加锁机制 A进程对一个操作的文件加了锁原创 2022-03-20 15:00:58 · 768 阅读 · 0 评论 -
11.5.1 共享内存的创建、使用和删除
11.5.1 共享内存的创建、使用和删除共享内存的创建本质上是两个接口,首先是调用shm_open返回文件描述符,然后是通过mmap将共享内存映射到进程的地址空间。两个函数的搭配很像SystemV的shmget函数和shmat函数。shm_open函数的接口定义如下:int shm_open(const char *name, int oflag, mode_t mode);这里的oflag标志要包含O_RDONLY或O_RDWR标志位,除此以外,可以选择的标志位还有O_CREA原创 2022-03-19 23:02:20 · 1647 阅读 · 0 评论 -
11.5.0 POSIX共享内存
11.5 POSIX共享内存前面曾经讲述过,mmap系统调用做了大量的工作,POSIX共享内存和前面的共享文件映射相比,并没有什么特殊之处。如果非要说有差别,那么差别就是,获取文件描述符的方式不同。普通文件映射获取 fd的方式 fd = open(filename,...); POSIX共享内存获取 fd的方式 fd = shm_open(name,...);使用 mmap映射到进程地址空间 addr = mmap(NULL,length,PROT_READ|PROT_WRITE,MAP原创 2022-03-19 22:37:29 · 543 阅读 · 0 评论 -
11.4.2 内存映射的相关接口
11.4.2 内存映射的相关接口mmap函数的接口定义如下:void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);这个函数的参数比较多。其中fd、offset和length这三个参数指定了内存映射的源,即将fd对应的文件,从offset位置起,将长度为length的内容映射到进程的地址空间。对于文件映射,调用mmap之前需要调用open取到对应文件的文件描述符。参数使用:第原创 2022-03-19 19:50:06 · 1060 阅读 · 0 评论 -
11.4.1 内存映射概述
11.4.1 内存映射概述mmap系统调用的作用是在调用进程的虚拟地址空间中创建一个新的内存映射。根据内存背后有无实体文件与之关联,映射可以分成以下两种:文件映射:内存映射区域有实体文件与之关联。mmap系统调用将普通文件的一部分内容直接映射到调用进程的虚拟地址空间。 一旦完成映射,就可以通过在相应的内存区域中操作字节来访问文件内容。这种映射也被称为基于文件的映射。匿名映射:匿名映射没有对应的文件。这种映射的内存区域会被初始化成0。 一个进程映射的内存可以与其他进程中的映射共享物理原创 2022-03-19 18:36:23 · 331 阅读 · 0 评论 -
11.4.0 内存映射mmap
11.4 内存映射mmap消息队列和信号量都已经介绍过了,按照正常的逻辑,本节应该介绍POSIX共享内存,为什么这里却要介绍内存映射mmap呢?这是因为内存映射mmap是POSIX共享内存的基础,内存映射完成了大量的基础性工作,临门一脚交给了共享内存。事实上POSIX共享内存也要和mmap配合使用。不理解mmap就不能很好地理解POSIX共享内存。更重要的是,纵然不提共享内存,mmap这个系统调用也是非常重要的,其重要程度远远超过POSIX共享内存。只要你在Linux平台上工作,每天就一定会执行原创 2022-03-19 18:02:53 · 383 阅读 · 0 评论 -
11.3.3 无名信号量的创建和销毁
11.3.3 无名信号量的创建和销毁无名信号量,由于其没有名字,所以适用范围要小于有名信号量。只有将无名信号量放在多个进程或线程都共同可见的内存区域时才有意义,否则协作的进程无法操作信号量,达不到同步或互斥的目的。所以一般而言,无名信号量多用于线程之间。因为线程会共享地址空间,所以访问共同的无名信号量是很容易办到的事情。或者将信号量创建在共享内存内,多个进程通过操作共享内存的信号量达到同步或互斥的目的。1.初始化无名信号量无名信号量的初始化是通过sem_init函数来完成的。原创 2022-03-19 17:42:04 · 438 阅读 · 0 评论