《UNUX环境高级编程》(14)高级I/O
1、引言
2、 非阻塞I/O
- 系统调用分为两类:低速系统调用和其他系统调用。低速系统调用是可能会使进程永远阻塞的一类系统调用,包括:
- 如果某些文件类型(如读管道、终端设备和网络设备)的数据并不存在,读操作可能使调用者永远阻塞。
- 如果数据不能被相同的文件类型立即接受(如管道中无空间、网络流控制),写操作可能会使调用者永远阻塞。
- 在某种条件发生之前打开某些文件类型可能会发生阻塞(例如以只写模式打开FIFO,那么在没有其他进程用读模式打开该FIFO时也要等待)
- 对已经加上强制性记录锁的文件进行读写
- 某些ioctl操作
- 某些进程间通信函数
- 非阻塞
I/O
使我们可以发出open
、read
和write
这样的I/O
操作,并使这些操作不会永远阻塞。如果这种操作不能完成,则调用立即出错返回,表示该操作如果继续进行将阻塞。 - 对于一个非阻塞的描述符如果无数据可读,则
read
返回-1
,errno
为EAGAIN
。 - 非阻塞
I/O
指的是文件状态标志,即与文件表项有关。会影响使用同一文件表项的所有文件描述符(即使属于不同的进程)。 - 注意,
read
函数阻塞的情况:read
函数只是一个通用的读文件设备的接口。是否阻塞需要由设备的属性和设定所决定。一般来说,读字符终端、网络的socket
描述字,管道文件等,这些文件的缺省read
都是阻塞的方式。如果是读磁盘上的文件,一般不会是阻塞方式的。但使用锁和fcntl
设置取消文件O_NOBLOCK
状态,也会产生阻塞的read
效果。 - 对于一个给定的文件描述符,有两种方式为其指定非阻塞
I/O
:- 如果用
open
获得描述符,指定O_NONBLOCK
标志 - 对于一个已经打开的文件描述符,则可调用
fcntl
,由该函数打开O_NONBLOCK
文件状态标志int flag = fcntl(fd, F_GETFL); //获取文件状态标志 flag |= O_NONBLOCK; int ret = fcntl(fd, F_SETFL, flag); //设置文件状态标志
- 如果用
- 实例: 一个非阻塞
I/O
的实例。它从标准输入读50000
个字节,并试图将它们写到标准输出上。该程序先将标准输出设置为非阻塞的,然后用for
循环进行输出,每次write
调用的结果都在标准错误上打印。其中set_fl
函数的介绍见3.14
节,get_fl
函数则类似于set_fl
函数。#include "apue.h" #include <errno.h> #include <fcntl.h>char buf[500000];int main(void) {int ntowrite, nwrite;char *ptr;ntowrite = read(STDIN_FILENO, buf, sizeof(buf));fprintf(stderr, "read %d bytes\n", ntowrite);set_fl(STDOUT_FILENO, O_NONBLOCK); /* set nonblocking */ptr = buf;while (ntowrite > 0) {errno = 0;nwrite = write(STDOUT_FILENO, ptr, ntowrite);fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno);if (nwrite > 0) {ptr += nwrite;ntowrite -= nwrite;}}clr_fl(STDOUT_FILENO, O_NONBLOCK); /* clear nonblocking */exit(0); }
-
若标准输出是普通文件,则
write
一般只调用一次。这里的文件/etc/services
大小为19605
字节,小于程序中的50000
字节,所以写入的大小也为19605
字节。如果文件大小大于50000
字节,那么写入的大小为50000
字节。lh@LH_LINUX:~/桌面/apue.3e/advio$ ls -l /etc/services -rw-r--r-- 1 root root 19605 10月 25 2014 /etc/services lh@LH_LINUX:~/桌面/apue.3e/advio$ ./nonblockw < /etc/services > temp.file read 19605 bytes nwrite = 19605, errno = 0 lh@LH_LINUX:~/桌面/apue.3e/advio$ ls -l temp.file -rw-rw-r-- 1 lh lh 19605 8月 9 13:15 temp.file
-
若标准输出是终端,则有时返回数字,有时返回错误,下面是运行结果。
- 该系统上,
errno
的值35
对应的是EAGAIN
。终端驱动程序一次能接受的数据量随系统而变。 - 在此实例中,程序发出了
9000
多个write
调用,但是只有500
个真正输出了数据,其余的都只返回了错误。这种形式的循环称为轮询,在多用户系统上用它会浪费CPU时间。14.4
节会介绍非阻塞描述符的I/O
多路转换,这是进行这种操作的一种比较有效的方法。 - 有时,可以将应用程序设计成多线程的,从而避免使用非阻塞
I/O
。如若我们能在其他线程中继续进行,则可以允许单个线程在I/O
调用中阻塞。但线程间的同步的开销有时却可能增加复杂性,于是导致得不偿失的后果。
- 该系统上,
-
3、 记录锁
- 当两个人同时编辑一个文件时,该文件的最后状态取决于写该文件的最后一个进程。但是对于有些应用程序如数据库,进程有时需要确保它正在单独写一个文件。因此可以使用记录锁机制。
- 记录锁的功能:当第一个进程正在读或者修改文件的某个部分时,使用记录锁可以阻止其他进程修改同一文件区。
- 其实应该称记录锁为 “字节范围锁” ,因为它锁定的只是文件中的一个区域(也可能是整个文件)
3.1、历史
- 这部分的内容不重要,略过。
3.2、fcntl
记录锁
-
3.14
节已经给出了该函数的原型int fcntl(int fd, int cmd, ... /* struct flock * flockptr */ );
- 与记录锁相关的
cmd
是F_GETLK
、F_SETLK
、F_SETLKW
。F_GETLK
:- 判断由
flockptr
描述的锁是否会被另外一把锁排斥(阻塞)。如果存在一把锁阻止创建flockptr
描述的锁,则该现有锁的信息将重写flockptr
指向的信息。如果不存在这种情况,除了l_type
设置为F_UNLCK
之外,flockptr
指向的结构中其他信息不变。 - 注意由于调用进程自己的锁并不会阻塞自己的下一次尝试加锁(因为新锁将替换旧锁),因此
F_GETLK
不会报告调用进程自己持有的锁信息。因此不能用它来测试自己是否在某一文件区域持有一把锁。
- 判断由
F_SETLK
:- 设置由
flockptr
所描述的锁(共享读锁或独占写锁)。如果失败fcntl
函数立即出错返回,errno
设置为EACCES
或EAGAGIN
- 设置由
F_SETLKW
:- 这个命令是
F_SETLK
的阻塞版本(w
表示等待wait
)。如果所请求的读锁或写锁因另一个进程当前已经对所请求部分进行了加锁而不能被授予,那么调用进程休眠。如果请求创建的锁已经可用,或者休眠被信号中断,则该进程被唤醒。
- 这个命令是
- 第三个参数是一个指向
flock
结构的指针。struct flock{short int l_type; /* 记录锁类型: F_RDLCK, F_WRLCK, or F_UNLCK. */short int l_whence; /* SEEK_SET、SEEK_CUR、SEEK_END */__off_t l_start; /* Offset where the lock begins. */__off_t l_len; /* Size of the locked area; zero means until EOF. */__pid_t l_pid; /* Process holding the lock. */};
- 对
flock
结构说明如下:l_type
:所希望的锁类型。F_RDLCK
(共享读锁)、F_WRLCK
(独占性写锁)、F_UNLCK
(解锁一个区域)l_whence
:指示l_start
从哪里开始。SEEK_SET
(开头)、SEEK_CUR
(当前位置)、SEEK_END
(结尾)l_start
:要加锁或解锁区域的起始字节偏移量l_len
:要加锁或解锁区域字节长度l_pid
:仅由F_GETLK
返回,表示该pid
进程持有的锁能阻塞当前进程。
- 关于加锁和解锁区域的说明还要注意以下事项:
- 锁可以在当前文件尾端处开始或者越过尾端处开始,但是不能在文件起始位置之前开始。
- 如果
l_len
为0
,则表示锁的范围可以扩展到最大可能偏移量。这意味着不管向该文件中追加写了多少数据,它们都可以处于锁的范围内(不必猜测会有多少字节被追加写到了文件之后) - 为了对整个文件加锁,设置
l_start
和l_whence
指向文件起始位置,并且指定长度l_len
为0
。
- 对
- 与记录锁相关的
-
fcntl
可以操作两种锁:共享读锁F_RDLCK
和独占性写锁F_WRLCK
- 任意多个进程在一个给定的字节上可以有一把共享的读锁
- 但是在一个给定字节上只能有一个进程有一把独占写锁。
- 如果在一个给定字节上已经有一把或多把读锁,则不能在该字节上再加写锁
- 如果在一个字节上已经有一把独占性写锁,则不能再对它加任何读锁。
- 如果一个进程对一个文件区间已经有了一把锁,后来该进程又企图在同一文件区间再加一把锁,那么新锁将替换已有锁。比如一个进程在某文件的
16-32
字节区间有一把写锁,然后又试图在16-32
字节区间加一把读锁,那么该请求成功执行,原来的写锁替换为读锁。 - 加读锁时,描述符必须是读打开;加写锁时,描述符必须是写打开。
-
需要注意以下两点:
- 用
F_GETLK
测试能否建立一把锁,然后用F_SETLK
或F_SETLKW
企图建立那把锁,这两者不是一个原子操作。不能保证两次fcntl
调用之间不会有另一个进程插入并建立一把锁 POSIX
没有说明下列情况会发生什么:- 第一个进程在某文件区间设置一把读锁,第二个进程试图在同一文件区间加一把写锁时阻塞,然后第三个进程则试图在同一文件区间设置另一把读锁。如果允许第三个进程获得读锁,那么这种实现容易导致希望加写锁的进程饿死。
- 用
-
文件记录锁的组合和分裂
- 在设置或释放文件上的一把锁时,系统按照要求组合或分裂相邻区。
- 例如在
100-199
字节是加锁区域,当需要解锁第150
字节时,则内核将维持两把锁:一把用于100-149
字节;另一把用于151-199
字节。 - 如果我们又对第
150
字节加锁,那么系统会把相邻的加锁区合并成一个区(100-199
字节),和开始时又一样了。
- 例如在
- 在设置或释放文件上的一把锁时,系统按照要求组合或分裂相邻区。
-
实例:请求和释放一把锁。为了每次都避免分配
flock
结构,然后又填入各项信息,可以用下图程序中的lock_reg
来处理这些细节。
- 因为大多数锁调用时加锁或解锁一个文件区域(命令
F_GETLK
很少使用),故通常使用下列5
个宏中的一个。这5
个宏都定义在apue.h
中(见附录B
)
- 因为大多数锁调用时加锁或解锁一个文件区域(命令
-
实例:测试一把锁。如果存在一把锁,它阻塞由参数指定的锁请求,则此函数返回持有这把现有锁的进程的进程
ID
,否则此函数返回0
。- 通过用下面两个宏来调用此函数(它们也定义在
apue.h
中)
- 注意,进程不能使用
lock_test
函数测试它自己是否在文件的某一部分持有一把锁。F_GETLK
命令的定义说明,返回信息指示是否有现有的锁阻止调用进程设置它自己的锁。因为F_SETLK
和F_SETLKW
命令总是替换调用进程现有的锁(若已存在),所以调用进程绝不会阻塞在自己持有的锁上。于是,F_GETLK
命令绝不会报告调用进程自己持有的锁。
- 通过用下面两个宏来调用此函数(它们也定义在
-
实例:死锁。该例中子进程对第
0
字节加锁,父进程对第1
字节加锁。然后,它们中的每一个又试图对对方已经加锁的字节加锁。 程序中介绍了8.9节中介绍的父进程和子进程同步例程。#include "apue.h" #include <fcntl.h>static void lockabyte(const char *name, int fd, off_t offset) {if (writew_lock(fd, offset, SEEK_SET, 1) < 0)err_sys("%s: writew_lock error", name);printf("%s: got the lock, byte %lld\n", name, (long long)offset); }int main(void) {int fd;pid_t pid;/** Create a file and write two bytes to it.*/if ((fd = creat("templock", FILE_MODE)) < 0)err_sys("creat error");if (write(fd, "ab", 2) != 2)err_sys("write error");TELL_WAIT(); /*set things up for TELL_xxx & WAIT_xxx */if ((pid = fork()) < 0) {err_sys("fork error");} else if (pid == 0) { /* child */lockabyte("child", fd, 0);TELL_PARENT(getppid()); /*tell parent we're done */WAIT_PARENT(); /*and wait for parent*/lockabyte("child", fd, 1);} else { /* parent */lockabyte("parent", fd, 1);TELL_CHILD(pid); /*tell child we're done */WAIT_CHILD(); /*and wait for parent*/ lockabyte("parent", fd, 0);}exit(0); }
运行该实例可以得到
lh@LH_LINUX:~/桌面/apue.3e/advio$ ./deadlock parent: got the lock, byte 1 child: got the lock, byte 0 parent: writew_lock error: Resource deadlock avoided child: got the lock, byte 1
- 检测到死锁时,内核必须选择一个进程接收出错返回。在本实例中,选择了父进程。选择父进程还是子进程出错返回随操作系统而定。
3.3、锁的隐含继承和释放
- 关于记录锁的自动继承和释放有3条规则。
- 锁与进程和文件两者相关联:当一个进程终止时,它所建立的锁全部释放;无论一个描述符何时关闭,该进程通过这一描述符引用的文件上的任何一把锁都会释放(这些锁都是该进程设置的)。
- 例如,在
close(fd)
后,在fd1
设置的锁被释放。dup
函数的使用方法见3.12
节fd1 = open(pathname, ...); read_lock(fd1, ...); fd2 = dup(fd1); close(fd2);
- 如果
dup
替换成open
,其效果也一样:fd1 = open(pathname, ...); read_lock(fd1, ...); fd2 = open(fd1); close(fd2);
- 例如,在
- 由
fork
产生的子进程不继承父进程所设置的锁。因为对于父进程获得的锁而言,子进程被视为另一个进程。 - 执行
exec
后,新程序可以继承原执行程序的锁。但是如果该文件描述符设置了close-on-exec
标志,则exec
之后释放相应文件的锁。
- 锁与进程和文件两者相关联:当一个进程终止时,它所建立的锁全部释放;无论一个描述符何时关闭,该进程通过这一描述符引用的文件上的任何一把锁都会释放(这些锁都是该进程设置的)。
3.4、FreeBSD实现
- 考虑一个进程,他执行下列语句(忽略出错返回)
在父进程和子进程暂停(执行fd1 = open(pathname,...); write_lock(fd1,0,SEEK_SET,1); // 该函数是自定义的,父进程在字节0上设置写锁 if((pid = fork()) > 0) { // 父进程fd2 = dup(f1);fd3 = open(pathname,...); } else if(pid == 0) { // 子进程read_lock(fd1,1,SEEK_SET,1); //该函数是自定义的,子进程在字节1上设置读锁 } pause();
pause()
)之后,数据结构的情况如下
- 可以看出来,文件记录锁信息是保存在文件
v节点
/inode节点
上的(而不是在文件表项中的),其实现是通过一个链表记录该文件上的各个锁,因此能保证多个进程正确操作文件记录锁。在图中显示了两个lockf
结构,一个是由父进程调用write_lock
形成的,另一个则是子进程调用read_lock
形成的。每一个结构都包含了相应的进程ID
。 - 在父进程中,关闭
fd1
、fd2
、fd3
中的任意一个都将释放由父进程设置的写锁。内核会从该描述符锁关联的inode
节点开始,逐个检查lockf
链表中的各项,并释放由调用进程持有的各把锁。
- 可以看出来,文件记录锁信息是保存在文件
- 实例:守护进程可用一把文件锁来保证只有该守护进程的唯一副本在运行,其
lockfile
函数实现如下:守护进程可用该函数在文件整体上加独占写锁。
另一种方法是int lockfile(int fd) {struct flock fl;fl.l_type = F_WRLCK;fl.l_start = 0;fl.l_whence = SEEK_SET;fl.l_len = 0;return fcntl(fd,F_SETLK,&fl); }
write_lock
函数定义lockfile
函数:#define lockfile(fd) write_lock((fd),0,SEEK_SET,0)
3.5、在文件的尾端加锁
- 在对相对于文件尾端的字节范围加锁解锁必须特别小心。如下面代码:
write_lock(fd,0,SEEK_END,0); write(fd,buf,1); un_lock(fd,0,SEEK_END); write(fd,buf,1);
- 刚开始获得一把写锁,该锁从当前文件尾开始,包括以后可能追加写到该文件的任何数据。当文件偏移量处于文件尾时,
write
一个字节将文件延伸了一个字节,因此该字节被加写锁。 - 但是其后的解锁是对当前文件尾开始包括以后可能追加写到该文件的任何数据进行解锁,因此刚才追加写入的一个字节保留加锁状态。之后又写入了一个字节,由此代码造成的文件锁状态如图。
- 刚开始获得一把写锁,该锁从当前文件尾开始,包括以后可能追加写到该文件的任何数据。当文件偏移量处于文件尾时,
相关文章:
《UNUX环境高级编程》(14)高级I/O
1、引言 2、 非阻塞I/O 系统调用分为两类:低速系统调用和其他系统调用。低速系统调用是可能会使进程永远阻塞的一类系统调用,包括: 如果某些文件类型(如读管道、终端设备和网络设备)的数据并不存在,读操作…...
第5讲:如何构建类的方法
【分享成果,随喜正能量】在这个社会上,对别人好一点,多站在别人的角度考虑,不要为小事争执,不要取笑他人,不要在别人背后嚼舌根,更不能逼人太甚。凡事退一步,对你有好处。。 《VBA中…...
【TypeScript】TS接口interface类型(三)
【TypeScript】TS接口interface类型(三) 【TypeScript】TS接口interface类型(三)一、接口类型二、实践使用2.1 常规类型2.2 设置属性只读 readonly2.3 设置索引签名2.4 设置可选属性2.5 函数类型接口 一、接口类型 TypeScript中的…...
Python web实战之Django 的 RESTful API 设计详解
关键词: Python, Web 开发, Django, RESTful API 1 API的一些事儿 1.1 什么是API? API是应用程序编程接口(Application Programming Interface)的缩写。它是一种定义了不同软件组件之间交互方式的规范。API允许不同的应用程序之间进行通信和…...
Python 程序设计入门(014)—— Python 的 Lambda 函数(匿名函数)
Python 程序设计入门(014)—— Python 的 Lambda 函数(匿名函数) 目录 Python 程序设计入门(014)—— Python 的 Lambda 函数(匿名函数)一、匿名函数的定义二、匿名函数的特征三、匿…...
【MySQL系列】表约束的学习
「前言」文章内容大致是MySQL的表的约束。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、MySQL表的约束1.1 空属性1.2 默认值(default)1.3 列描述(comment)1.4 zerofill1.5 主键(primary ke…...
低功耗LoRaWAN国产低功耗LoRa+RF射频前端芯片XD6500S
目录 典型应用XD6500S简介芯片特性 LoRa系列选型参考 LoRa是为低数据速率、远距离距离和超低功耗而优化的扩频协议,用于LPWAN应用程序的通信。 典型应用 一、智慧农业 智慧农业大田解决方案利用传感设备、自动化控制设备、气象站实时监测采集田间土壤墒情、气象…...
【基础IO】文件系统 {磁盘的物理结构,存储结构,逻辑结构;CHS 和 LBA 寻址方式;磁盘分区和块组;文件inode;软硬链接}
文件系统 文件分为: 内存文件:被进程打开的文件,文件被加载到内存中供进程快速读写。磁盘文件:没有被打开的文件,保存在磁盘上。磁盘文件被分门别类的存储和管理,用于支持更好的存取。 提示: …...
全角字符和半角字符
全角字符的由来 全角符号是双字节中文编码的历史遗留问题。当年在纯文本的界面中,为了让西文和中日韩的方块字对齐,就让西文字母、数字和标点也占用一个汉字的视觉空间,并使用 2 个字节存储。后来,其中的一些全角字符因为比较有用…...
【java】【经验】java: 错误: 不支持发行版本 6
前言:配置过maven之后,发现原来的一些项目运行提示java: 错误: 不支持发行版本 6或者java: 错误: 不支持发行版本 5,主要原因:是因为项目使用的Java版本和安装的Java版本不符合 目录 1 设置项目java版本 2 设置模块版本 3 set…...
Spring Boot3.0(四):Thymeleaf 使用详解
Thymeleaf 介绍 简单说,Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点: 1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以…...
杨辉三角【Java二维数组】
这个代码中,我们定义了一个二维数组nums来存储杨辉三角的每一个数字。在for循环中,我们初始化每一行的第一个和最后一个数字,并且根据上一行的数字来计算出中间的数字。 接着,我们使用两个嵌套的for循环来输出杨辉三角。第一个循…...
解决SpringBoot服务返回数据存在$ref $.data等相关问题
1、场景 在日常的开发中,我们数据接口返回数据使用了FastJson序列化数据,当返回一个数据list时候出现" r e f " " ref" " ref"".data" 等类似乱码一样的数据,当时我比较匪夷所思,我写…...
【iOS安全】开启任意app的WebView远程调试
参考:https://mp.weixin.qq.com/s/bNKxQaVrPaXsZ5BPbsXy7w (来自周智老师的公众号) 概述 Safari 有一个内置的前端调试器, 在iPhone通过局域网或者USB连接MacBook 并启用Safari 远程调试之后,前端调试器默认情况下对…...
windows下 java程序无窗口启动、无窗口启动java -jar
创建一个.bat文件,其他照抄,注意一下你自己的jar包路径和日志路径:例:java -jar C:\data\operation-1.0-SNAPSHOT.jar > C:\data\log.log 2>&1 & ------------文件内容 echo off %1 mshta vbscript:CreateObject(…...
锦程消费金融业务生变:App下架,部分自营信贷暂停
来源 | 镭射财经(leishecaijing) 被誉为消金房抵一哥的锦程消费金融,调整旗下自营信贷业务,展业回归房抵场景。 「镭射财经」独家获悉,锦程消费金融已暂停部分自营小额信贷业务,旗下锦囊贷App已经下架&am…...
Python爬虫在框架下的合规操作与风险控制
大家好!作为一名专业的爬虫代理供应商,我今天要和大家分享一些关于Python爬虫在法律框架下的合规操作与风险控制的知识。随着互联网的发展,数据爬取在商业和研究领域扮演着重要的角色,但我们也必须遵守相关法律和规定,…...
前端页面如何创建表格?table的结构、属性有哪些?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ HTML是什么?⭐ table标签的属性⭐ 注意事项⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏…...
神码ai伪原创工具【php源码】
大家好,小编为大家解答python炫酷烟花表白源代码的问题。很多人还不知道html代码烟花特效python,现在让我们一起来看看吧! 火车头采集ai伪原创插件截图: 目录 前言 环境准备 代码编写 效果展示 前言 Python实现浪漫的烟花特效 现在…...
Linux命令200例:mkdir用于创建目录(常用)
🏆作者简介,黑夜开发者,全栈领域新星创作者✌。CSDN专家博主,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 &…...
C语言内嵌汇编
反编译(二进制文件或者so库) objdump --help objdump -M intel -j .text -ld -C -S out > out.txt #显示源代码同时显示行号, 代码段反汇编-M intel 英特尔语法-M x86-64-C:将C符号名逆向解析-S 反汇编的同时,将反汇编代码和源代码交替显…...
《网络是怎样连接的》(三)
《网络是怎样连接的》(二.2)_qq_38480311的博客-CSDN博客 本文主要取材于 《网络是怎样连接的》 第三章。 简述:本文主要内容是解释 通过网线传输出去的包是如何经过集线器、交换机和路由器等网络设备,最终进入互联网的。 信号…...
SpringBoot 配置文件
一、配置文件作用 整个项目中所有重要的数据都是在配置文件中配置的,比如: 数据库的连接信息(包含用户名和密码的设置); 项目的启动端口; 第三方系统的调用秘钥等信息; 用于发现和定位问题的…...
【K8S】 deployment.yaml文件与Service yaml文件详解
目录 deployment.yaml文件详解Service yaml文件详解 deployment.yaml文件详解 apiVersion: extensions/v1beta1 #接口版本 kind: Deployment #接口类型 metadata:name: cango-demo #Deployment名称namespace: cango-prd #命名空间l…...
GMSL 9296芯片对GMSL链路 插损/回损/线束要求
基于美信 9296的芯⽚ 对于GMSL信号链路上的需求如下: 1:插损 频段2M~3.5GHZ 在3G时需要⼩于-21db。通信速率 6Gbps/187Mbps 频段2M~3.5GHZ 在3G时需要⼩于-18db。通信速率 6Gbps/1.5Gbps 频段2M~2GHZ 在1.5G时需要⼩于-19.5db。通信速率 3Gbps/187Mbps …...
用库造一个list的轮子 【C++】
文章目录 list的模拟实现默认成员函数构造函数拷贝构造函数赋值运算符重载析构函数 迭代器迭代器为什么要存在?const_iteratorbegin和end inserterasepush_back && pop_backpush_front &&pop_frontswap 完整代码 list的模拟实现 默认成员函数 构造…...
java中的,>>,<<位运算
目录 二进制 >>,<< & 二进制 计算机内部使用二进制计数 二进制:在数学和数字电路中指以2为基数的记数系统,以2为基数代表系统是二进位制的,这一系统中,通常用两个不同的符号0(代表零)和…...
成功解决Android设备adb连接后显示device unauthorized
一、提出问题 在电脑通过USB连接新的Android设备,想要通过adb来进行一些操作时,却发现命令提示符上在输入下面命令后显示设备未授权的信息也就是"unauthorized" adb devices二、不可行的解决方案 有人提出的解决方案是打开Android设备的开发…...
初识mysql数据库之引入mysql客户端库
目录 一、下载第三方库 1. 准备工作 1. 使用mysql官网提供的库 2. yum源安装 二、测试第三方库是否可用 三、mysql常用接口介绍 1. 查看官方文档 2. 初始化 3. 关闭mysql 4. 连接mysql 5. 下达sql指令 四、一个简单的C客户端库连接mysql程序 1. 头文件 2. 初始化…...
勘探开发人工智能技术:机器学习(1)
0 提纲 2.1 什么是机器学习 2.2 不确定性 2.3 数据类型 2.4 分类、回归、聚类 2.5 分类问题的训练与测试 2.6 性能评价指标 1 什么是机器学习 对于西瓜这个抽象类来说,它具有“色泽”,“根蒂”,“敲声”三个属性: 通过观察这个…...
电子商务做网站骗钱怎么办/指数函数图像
数据类型之 字符串一字符串操作创建及赋值x abcdex "abcde"x abcdex """abcde"""#通过str方法将其他类型转化为字符串类型x str([1234])访问字符串通过索引 和 通过切片访问任意部分字符串astring abcd#通过索引print astring[1]#通…...
家装平面设计主要做什么/福州网站seo公司
音视频实践学习 android全平台编译ffmpeg以及x264与fdk-aac实践ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器android全平台编译ffmpeg合并为单个库实践android-studio使用cmake编译ffmpeg实践android全平台下基于ffmpeg解码MP4视频文件为YUV文件android全平台编译…...
2019怎么做网站赚钱/广告代运营
PS:时间太久已经找不到原文链接了,若有侵权请联系删除。 运行Pytorch代码的时候遇到: RuntimeError: cuda runtime error (35) : CUDA driver version is insufficient for CUDA runtime version at /pytorch/aten/src/THC/THCGeneral.cpp:7…...
怎么样在网站上做跳转/海南百度推广总代理
用<c:choose> <c:when> <c:otherwise>即可。 refurl:http://bluexp29.blog.163.com/blog/static/3385814820101535831912/ http://tianhandigeng.iteye.com/blog/938253...
山东做网站公司哪家好/临沂google推广
文章目录10.1 Java与线程10.1.1 线程的实现1. 使用内核线程实现2. 使用用户线程实现3. 混合实现4.Java线程的实现10.1.2 Java线程调度10.1.3 状态转换10.1 Java与线程 10.1.1 线程的实现 线程的引入,可以把一个进程的资源分配和执行调度分开,各个线程既…...
深圳市营销型网站/百度广告联盟平台
假设我有一个c库,它以某种方式操纵着一个世界。在我想在python中使用这个库。我希望能够编写简单的python脚本来表示世界管理的不同场景。在我有创造和毁灭世界的功能:void*创建(void);int摧毁(虚空*世界)下面是一些python代码:im…...