Linux系统编程
Linux_c 系统编程
Ma浩然
嵌入式打杂专家
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
16_网络IPC16-TCP与UDP的消息保护边界
根据以上所说,可以这样理解,TCP为了保证可靠传输,尽量减少额外开销(每次发包都要验证),因此采用了流式传输,面向流的传输,相对于面向消息的传输,可以减少发送包的数量。而UDP,由于面向的是消息传输,它把所有接收到的消息都挂接到缓冲区的接受队列中,因此,它对于数据的提取分离就更加方便,但是,它没有粘包机制,因此,当发送数据量较小的时候,就会发生数据包有效载荷较小的情况,也会增加多次发送的系统发送开销(系统调用,写硬件等)和接收开销。因此,应该最好设置一个比较合适的数据包的包长,来进行UDP数据的发送。原创 2024-07-26 16:46:28 · 593 阅读 · 0 评论 -
17_高级进程间通信 UNIX域套接字1
第3个参数protocol,表示协议,可以是SOCK_STREAM或者SOCK_DGRAM。用SOCK_STREAM建立的套接字对是管道流,与一般的管道相区别的是,套接字对建立的通道是双向的,即每一端都可以进行读写。不管是数据流还是数据报协议,unix域套接字都是可靠的,不丢包的。示例代码抄录自:https://blog.csdn.net/bytxl/article/details/47861469。第1个参数domain,表示协议族,只能为AF_LOCAL或者AF_UNIX;命名UNIX域套接字。原创 2024-07-21 17:14:39 · 688 阅读 · 0 评论 -
16_网络IPC15-Socket Select 构建高效网络通信模型
使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。在网络编程中,当涉及到多客户访问服务器的情况,我们首先想到的办法就是fork出多个进程来处理每个客户连接,或者使用多线程处理。现在,我们同样可以使用select来处理多客户问题,而不用fork或者多线程,只在单线程既可处理。以下代码例程照抄自:https://blog.csdn.net/weixin_41010318/article/details/80257177。原创 2024-07-21 12:38:29 · 327 阅读 · 0 评论 -
16_网络IPC14-Socket缓冲区,可读可写条件
1 首先会检查缓冲区,如果缓冲区的可用空间长度小于要发送的数据,那么 write()/send() 会被阻塞(暂停执行),直到缓冲区中的数据被发送到目标机器,腾出足够的空间,才唤醒 write()/send() 函数继续写入数据。2 如果TCP协议正在向网络发送数据,那么输出缓冲区会被锁定,不允许写入,write()/send() 也会被阻塞,直到数据发送完毕缓冲区解锁,write()/send() 才会被唤醒。1 首先会检查缓冲区,如果缓冲区中有数据,那么就读取,否则函数会被阻塞,直到网络上有数据到来。原创 2023-01-30 11:21:33 · 2057 阅读 · 1 评论 -
16_网络IPC13-流式套接字_静态进程池版
注意:accept()本身就可以实现单一的连接,也就是说他本身就可以实现互斥。当有N个进程阻塞在accept()位置的时候,只有一个进程能正常连接,其他进程依然阻塞。此处静态进程池的缺点:此处进程池中有4个进程在同时准备接收C端数据请求,也就是说该S端程序,最多也只能够同时对接4个C端,而如果一下来了一万个C端请求,那么此时也只能一次性处理四个C端,下一次再处理四个,也就是四个 四个的处理,显然是不够的。所以如果需要 继续优化,可以使用动态内存池,即 保证线程池中至少有n1个进程在空闲等待接收请求,最原创 2021-04-08 00:20:47 · 329 阅读 · 1 评论 -
16_网络IPC12-流式套接字_并发版
流式套接字 并发版:如果多个C端向S端请求数据,并且服务时间较长,那么以单进程执行的话,那么多个请求,效率非常低,所以改进为 并发版本server.c#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <string.h>#include <原创 2021-04-08 00:19:41 · 309 阅读 · 1 评论 -
16_网络IPC11-流式套接字
C端1 获取socket socket()2 给socket取得地址(可省略) bind() 绑定IP地址和端口3 发送连接 connect()4 收发消息 recv()5 关闭连接 close()S端1 获取socket socket()2 给socket取得地址 bind() 绑定IP地址和端口3 将socket置为监听模式 lsiten()4 接受连接 accept()5 收发消息 send()6 关闭连接 close()listen() 监听一个SOCKETNAME原创 2021-04-08 00:18:17 · 651 阅读 · 1 评论 -
16_网络IPC10-TCP传输简析
可以发现 UDP方式传输中,是有大段时间在等待传输的,等ACK 发数据。怎么样能快一点呢?缩短等待时间:C端不是只发一次就开始等待,而是发送n个包,一直发,直到发满 RTT等待时间,即一直发,直到收到第一次ACK 为止,然后以后 每收到一个ACK 发一个包,这样的机制本质就是 把当前很多包扔出去,不等待,用包的数量最大限度抢占沿途传输的资源,沿途路由的等待队列其实是公共资源,大家都在用,所以一直发包 就可以抢占到沿途路由的等待队列,就算丢包也没关系,反正都有ACK编号,重新发就好了。也就是说,一次性原创 2021-04-08 00:12:16 · 315 阅读 · 1 评论 -
16_网络IPC9-UDP传输简析
UDP传输丢包,是由于阻塞造成的。路由有等待队列,并不是我的数据包从本路由到下一个路由是无条件发送的,而是有等待队列,这个等待队列会有丢包的算法实现。比如当前队列已经排列百分之N的容量时,就会随机的丢包等操作。解决:闭环流控(停等式流控),牺牲丢包率,来保证我们一定能收到内容。问题1 发送端发送后,接收端会在一段时间后才能收到消息,可能有n个路由,需要排队问题2:发送端发送消息后,结果丢包了,在一定时间后没有收到接收端ACK,则重新发送消息问题3:发送端发送消息后,接收端收到了数据,并且发送原创 2021-04-07 23:32:54 · 315 阅读 · 1 评论 -
16_网络IPC8-广播与组播
getsockopt, setsockopt 获取设置Socket选项NAME getsockopt, setsockopt - get and set options on socketsSYNOPSIS #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int getsockopt(int sockfd, int level原创 2021-04-01 23:00:23 · 414 阅读 · 1 评论 -
16_网络IPC7-动态报式套接字传输
注意,只要涉及到网络传输内容,传输的内容从来不会用到指针,因为如果是跨主机传输,两个设备上的某个地址中的数据是不同的,传递指针没有意义,如上一节中的struct msg_st{ char name[NAMESIZE];//绝对不可以用指针,跨主机传输地址没有意义,A机器的A1地址 传到B机器 没有任何用处。 uint32_t math; uint32_t chinese;}__attribute__((pack));为了突破传输数据中 名字的大小限制,使用柔性数组#define NAMEM原创 2021-03-30 23:42:33 · 317 阅读 · 1 评论 -
16_网络IPC6-报式套接字传输
需要掌握:socket(),获取SOCKETbind(), 绑定SOCKET到本地地址inet_pton(), IP地址格式转换:点分式 --> 大整数recvfrom(),用于报式套接字,从 SOCKET上接收信息recv(), 用于流式套接字,从 SOCKET上接收信息inet_ntop(),IP地址格式转换:大整数格式 --> 点分式格式send(), 用于流式套接字 向SOCKET发送数据sendto(),用于报式套接字,向SOCKET发送数据跨主机通信注意:被动端原创 2021-03-18 21:03:08 · 592 阅读 · 1 评论 -
16_网络IPC5-套接字选项
原创 2024-07-20 18:04:48 · 199 阅读 · 0 评论 -
16_网络IPC4-数据传输
Socket 只是通信节点,通信之前需要连接,即发送端发送之前 需要知道对端的地址,才能找到对端的socket节点,才能发送成功。而接收端不同,接收函数 如 recv () 不需要一定知道对端地址,因为接收端只需要监控本机的socket即可。Socket 只是通信节点,通信之前需要连接,即发送端发送之前 需要知道对端的地址,才能找到对端的socket节点,才能发送成功。而接收端不同,接收函数 如 recv () 不需要一定知道对端地址,因为接收端只需要监控本机的socket即可。原创 2024-07-20 17:59:58 · 356 阅读 · 0 评论 -
16_网络IPC3-建立连接
服务端使用 listen() 表明自己愿意接受连接,并标明最多连接客户端的数量,理解为服务端对系统声明,我已经准备好接受客户端的连接的,最多能接受多少客户端的连接。然后使用 accept() 开始等待客户端的连接。原创 2024-07-16 23:22:18 · 252 阅读 · 0 评论 -
16_网络IPC2-寻址
不同的协议族 来 绑定自己这端的地址 所用的结构体是不一样的。所以我们的处理方式是:我们用的是哪一个协议族,就把该协议族地址作为addr ,然后再把地址长度写到addrlen。采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。采用大小模式对数据进行存放的主要区别在于在存放的字节顺序,大端方式将高位存放在低地址,小端方式将高位存放在高地址。AF_INET 协议族中的 协议地址类型为 struct sockaddr_in。原创 2024-07-16 23:18:19 · 305 阅读 · 0 评论 -
16_网络IPC1-套接字描述符
用户数据报协议(UDP) 与 传输控制协议(TCP)文件描述符函数使用套接字的行为。原创 2024-07-15 22:08:52 · 264 阅读 · 0 评论 -
15_进程间通信7-POSIX信号量
关闭操作只是简单地结束了调用进程与信号量之间的关联,而信号量本身在系统中仍然存在。这意味着,即使调用了 sem_close,信号量也不会立即从系统中被删除,只要还有其他进程仍然使用该信号量1。当调用 sem_unlink 时,如果系统中没有其他进程再使用该命名信号量,那么该信号量就会被彻底地从系统中移除2。简而言之,sem_close 只是断开了调用进程与信号量的关联,而 sem_unlink 则是从系统中彻底移除了信号量,确保了资源的有效利用和避免闲置的信号量组占用系统资源。原创 2024-07-11 15:48:00 · 462 阅读 · 0 评论 -
15_进程间通信6-共享存储
Shared MemoryNAME分配一个System V共享内存段 shmget - allocates a System V shared memory segmentSYNOPSIS #include <sys/ipc.h> #include <sys/shm.h>/*key:如果没有亲缘关系的进程中 创建和获取 和之前 消息队列是一样的如果在有亲缘关系的进程中,fork()之后,每一个子进程都可以拿到父进程创建的 k原创 2021-03-17 10:56:12 · 344 阅读 · 0 评论 -
15_进程间通信5-信号量数组
NAME semget - get a System V semaphore set identifier :创建一个新的信号量或获取一个已经存在的信号量的IDSYNOPSIS #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>/*key:如果没有亲缘关系的进程中 创建和获取 和之前 消息队列是一样的如果在有亲缘关系的进程中原创 2021-03-15 21:03:06 · 572 阅读 · 0 评论 -
15_进程间通信4-消息队列
XSI -> SysVIPC -> Inter process communication 进程间通信的三种机制主动端:先发包的一方被动端:先收包的一方 ,一定是被动端先运行 等着收包mhr@ubuntu:~/Desktop/xitongbiancheng/communication$ ipcsMessage Queues 消息队列 ,双工key msqid owner perms used-bytes messages msgge原创 2021-03-15 20:23:18 · 485 阅读 · 1 评论 -
15_进程间通信3-命名管道FIFO
匿名管道:piepe(),磁盘上看不到文件,相当于直接给了我们一个文件描述符或者FILE*。导致最直接的结果就是 :如果两个进程之间没有血缘关系,是不能用匿名管道进行通信的,因为另一个进程找不到文件位置。命名管道:mkfifo(), 从磁盘上看到的文件类型为P 的文件。没有血缘关系的进程之间 可以用命名管道进行通信。本质上就是当前磁盘上存在的一个文件。XSI :消息队列,信号量数组,共享内存。指定我们所创建的命名管道的名字。内核提供,单工,自同步机制。管道必须要凑齐读写双方。原创 2024-06-19 21:51:37 · 282 阅读 · 0 评论 -
15_进程间通信2-popen
原创 2024-06-19 21:50:08 · 217 阅读 · 0 评论 -
15_进程间通信1-匿名管道
同机通信:管道XSI :消息队列,信号量数组,共享内存不同机器间通信socket 网络套接字管道必须要凑齐读写双方内核提供,单工,自同步机制匿名管道:piepe(),磁盘上看不到文件,相当于直接给了我们一个文件描述符或者FILE* 。导致最直接的结果就是 :如果两个进程之间没有血缘关系,是不能用匿名管道进行通信的,因为另一个进程找不到文件位置。命名管道:mkfifo(), 从磁盘上看到的文件类型为P 的文件。没有血缘关系的进程之间 可以用命名管道进行通信。本质上就是当前磁盘上存在的一个文原创 2021-03-15 20:17:55 · 298 阅读 · 1 评论 -
十四_高级IO7-文件锁,lockf()
文件锁的方法:fcntl()lockf()flock()NAME lockf - apply, test or remove a POSIX lock on an open fileSYNOPSIS #include <unistd.h>/*fd:需要锁的目标文件len: 要锁多长,0表示 文件有多长 锁多长,即加锁到文件末端,就算文件加长 也会随之锁上cmd :实现的命令F_LOCK 解锁,阻塞式加锁F_TLOCK 尝试加锁,非阻塞式原创 2021-03-12 14:25:06 · 463 阅读 · 1 评论 -
十四_高级IO6-记录锁 fcntl()
记录锁 flockptr 参数说明。多进程与单进程 对记录锁的使用区别。记录锁 cmd 参数说明。记录锁的 组合 和 分裂。原创 2024-07-09 14:36:04 · 312 阅读 · 0 评论 -
十四_高级IO5-mmap()内存映射
存储映射IO:mmap(): 将一块内存或者是某一个文件的存储内容 映射到当前进程空间里面来。结果就是 我们在当前进程中访问目标空间中的数据。NAME mmap, munmap - map or unmap files or devices into memorySYNOPSIS #include <sys/mman.h>/* 映射,返回值为映射到的最终地址。addr: 目标内存空间 放到当前进程空间的起始地址,若为空,则函数自己找可用的位置leng原创 2021-03-12 11:37:52 · 458 阅读 · 1 评论 -
十四_高级IO4- IO多路转接之 epoll() 监视文件描述符读,写等状态
epoll VS pollpoll() 可以理解为 我们在用户态 创建并维护一个结构体数组,而 epoll() 则是相当于,poll 中的结构体数组被放在内核态,内核为我们维护该数组,内核为我们提供一些方法(系统调用)来管理这个数组。NAME epoll_create, epoll_create1 - open an epoll file descriptorSYNOPSIS #include <sys/epoll.h>//创建一个epoll的句柄,当创建好原创 2021-03-12 09:51:27 · 501 阅读 · 1 评论 -
十四_高级IO3-IO多路转接之 poll() 监视文件描述符读,写等状态
poll 引进: 补充 select()的不足。他俩的区别在于:1 poll() 的 监视现场位置 和 监视结果位置分开存放,不需要向select()一样 每次返回都发生覆盖,不需要重复设置监视现场2 poll() 所能监控的状态有7中,并且可以自己添加需要的其他状态位,比select()多NAME poll, ppoll - wait for some event on a file descriptor以文件描述符为单位,组织事件,正好和 select()相反。SYNOPSIS原创 2021-03-11 17:34:26 · 444 阅读 · 1 评论 -
十四_高级IO2-IO多路转接-select()监视文件描述符读,写,异常状态
为什么引入多路转接:在前面 状态机实现 拷贝两个设备之间的数据的程序中,可以发现这样的问题:程序在运行期间,一定是一个忙等的状态,CPU 使用率很高,很浪费CPU时间,原因在于程序其实大部分时间都在忙于 判断假错,重读 重写的状态中循环。这个属于IO 密集,负载不密集的任务,即数据量不大,但是IO 很密集。对于IO密集型的任务 可以对程序进行IO多路转接,本质就是监视文件描述符的行为,当 当前文件描述符发生了我感兴趣的行为的时候,才会去做后续操作,如前面 两个设备之间的数据交换,前面的做法是盲推,一直不停原创 2021-03-11 16:03:57 · 585 阅读 · 0 评论 -
十四_高级IO1-非阻塞IO以及fcntl()
回顾:阻塞IO 假错 :EINTR ,阻塞的系统调用被信号打断非阻塞IO 假错 :EAGAIN,表示现在没有数据 Try again #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ ); F_GETFL (void) //获取文件访问方式和文件状态标志 Get the file access mode and原创 2021-03-05 12:35:12 · 365 阅读 · 1 评论 -
十一_线程5-条件变量
为什么要有条件变量:为了弥补互斥锁的不足互斥锁的不足:线程只有持锁执行,无锁阻塞(pthread_mutex_lock)两种状态,而如果某个线程是 根据 共享数据的某个变化是否发生 作为依据 来做其他操作。那么如果用互斥锁来实现的话,那么该线程会重复如下操作:申请持锁成功 判断 (共享数据的某个变化是否发生) 如果有发生,执行其他操作 如果没发生,解锁,(加sleep()会影响效率)并重新申请持锁申请持锁失败 阻塞(pthread_mutex_lock) 等待持锁如果 共享数据的某个变化原创 2021-03-02 16:32:14 · 372 阅读 · 1 评论 -
十一_线程4-互斥锁分析
引入互斥量:线程间 竞争故障:实验1:线程间竞争故障,用sleep()放大竞争故障#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <pthread.h>#define THRNUM 20#define FNAME "/home/mhr/Desktop/xitongbiancheng/parallel/threa原创 2021-03-01 16:00:26 · 509 阅读 · 1 评论 -
十一_线程3-线程的取消
pthread_cancel() : 取消线程pthread_setcancelstate() :设置 是否允许取消pthread_setcanceltype(): 设置取消方式,异步 或者 推迟pthread_testcancel(): 设置一个取消点pthread_detach() : 线程分离前面说到的 pthread_join() 线程收尸,是必须要等线程执行结束才能收尸,而有时候不需要目标线程执行结束 就要结束他,那么怎么收尸呢?pthread_cancel() + pthread原创 2021-02-28 17:31:24 · 317 阅读 · 1 评论 -
十一_线程2-线程标识的获取,比较,线程的创建,结束,收尸,线程栈清理
pthread_equal(),比较线程IDNAME pthread_equal - compare thread IDs 比较两个线程IDSYNOPSIS #include <pthread.h> int pthread_equal(pthread_t t1, pthread_t t2);// 不清楚 线程ID 类型,不能直接按照int类型数值的比较方法。用-pthread编译并链接。如果两个线程id相等,则pthread_equal(原创 2021-02-28 15:52:08 · 418 阅读 · 1 评论 -
Linux系统编程52 信号 - 实时信号
标准信号特点:1 标准信号会丢失2 标准信号 没有一个严格的响应顺序要求,未定义行为。标准信号中有两个未定义行为的信号,留给我们使用:SIGUSR1,SIGUSR2实时信号用于解决标准信号的不足:1 实时信号不会丢失2 实时信号响应有顺序要求实时信号实验:kill -l 查看信号,选择40) SIGRTMIN+6 信号#include <stdio.h>#include <stdlib.h>#include <signal.h>#include原创 2021-02-26 19:15:01 · 527 阅读 · 0 评论 -
十_信号14 - system()
意思是 应在在调用 system() 函数前 阻塞 SIGCHLD 信号,否则,子进程结束的时候,系统会向该进程(父)发送 SIGCHLD信号,则该进程认为是自己的一个子进程结束了,于是调用 wait函数获取子进程的终止状态。这本来是正常的操作,但是在使用 system()时候,这样的操作 会影响到 system函数内部的 wait()操作,导致system()内部获取子进程的终止状态的 wait()函数获取错误的状态,并将此错误的返回状态return到调用者。原创 2024-06-02 19:11:14 · 356 阅读 · 0 评论 -
十_信号13 - abort()
2 要么在 SIGABRT信号的处理函数中 清理缓冲区并自己退出进程。如果信号处理函数中没有执行退出进程操作,返回到 abort()函数中,要求在 abort()函数中结束进程,不能返回到其调用者。1 首先进程不能忽略 SIGABRT信号。原创 2024-06-02 19:08:38 · 333 阅读 · 0 评论 -
十_信号12 - sigsuspend() 设置信号集状态 与 挂起 的原子操作
NAME sigsuspend, rt_sigsuspend - wait for a signalSYNOPSIS #include <signal.h> int sigsuspend(const sigset_t *mask);功能:以下三步为原子操作第一步:设置当前进程信号集状态为 目标信号集状态mask,并保存进程旧的信号集状态为 oldmask//解除对于某个信号集的阻塞状态后第二步:马上进入等待信号阶段第三步:收到信号后 设原创 2021-02-26 12:33:49 · 1072 阅读 · 2 评论 -
十_信号11 - 函数sigsetjmp() 和 siglongjmp()
也就是说,正常情况下,当捕捉到一个信号,并调用该信号的信号处理程序时,被捕捉的信号会被加入到当前进程的信号屏蔽字中,以防止在本次信号处理程序还没有完成的时候,再次触发该信号, 发生重入。而sigsetjmp 可以设置选项保存 当前进程的信号屏蔽字,在信号处理程序中在屏蔽字中添加该信号,避免重入,而siglongjmp 则在返回时候可以恢复到之前的信号屏蔽字。而setjmp 与 longjmp 的组合使用。并不会在 从信号处理程序返回后 将屏蔽的信号恢复,即不会恢复执行该信号处理程序之前的信号屏蔽字状态。原创 2024-06-02 19:05:18 · 497 阅读 · 0 评论
分享