版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第6章 文件处理与进程控制,.,2,本章要点,1、文件描述符的概念 2、系统调用的基本概念 3、文件读写等处理方法 4、进程的概念 5、进程控制与进程间的通信 6、嵌入式Linux中对串口的操作,.,3,6.1嵌入式Linux的文件处理,.,4,6.1.1文件描述符及文件处理,1、文件及文件描述符 由于在Linux下设备和目录都看作是文件,因此,Linux中的文件有4种类型:普通文件、目录文件、链接文件和设备文件。 Linux的内核利用文件描述符访问文件。文件描述符是非负整数,它是一个索引值,并指向内核中每个进程打开文件的记录表。当打开一个现存文件或新建一个文件时,内核会向进程返回一个文件描述
2、符。当读写文件时,也需要使用文件描述符来指定待读写的文件。,.,5,2、系统调用,所谓系统调用是指操作系统提供给用户程序调用的一组“特殊”接口,用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务。例如用户可以通过进程控制相关的系统调用来创建进程、实现进程调度、进程管理等。,.,6,3、文件处理,Linux系统的文件处理,主要是指进行打开文件、读文件、写文件及关闭文件等I/O操作。大多数情况下,只需用到5个函数:open、read、write、lseek 和close。这几个函数不需要经过缓冲就能立即执行,因此,被称之为不带缓存的I/O操作,即每一个函数都只调用内核中的一个系统调用。,
3、.,7,6.1.2open函数和close函数,.,8,1、open函数,open函数用于打开或创建文件。 调用open函数所需要的头文件如下: #include #include #include 其函数为: int open(const char *pathname, int oflag, int perms ) ; 函数返回值:若文件打开成功则返回文件描述符,若出错则返回-1。,.,9,2、close函数,close函数用于关闭一个打开的文件,所需要的头文件为: #include 其函数为: int close(int fd); 函数返回值:若成功为0,若出错为-1。 关闭文件函数clo
4、se的参数fd为文件描述符。,.,10,3、示例,【例6-1】用可读写方式新建(打开)一个文件。 详见教材,.,11,6.1.3read函数、write函数和lseek函数,.,12,1、read函数,read函数从打开的文件中读取数据。 调用read函数所需要的头文件: # include 其函数原型为: ssize_t read(int fd, void *buf, size_t count); 函数返回值为读到数据的字节数,若返回值为0,则已经到达文件尾,若返回-1则为出错。,.,13,2、write函数,write函数用于向打开的文件实现写入数据的操作。写操作的位置从文件的当前位移量处
5、开始。若磁盘已满或超出该文件的长度,则write函数返回错误值。 调用write函数所需要的头文件: #include 其函数原型为: ssize_t write(int fd, void *buf, size_t count); 函数返回值为已写入数据的字节数,若返回-1则出错。,.,14,3、lseek函数,lseek函数用于在由指定的文件描述符的文件中将文件指针定位到相应的位置,以进行读写操作。 调用lseek函数所需要的头文件: #include #include 其函数原型为: off_t lseek(int fd, off_t offset, int whence); 函数返回值为
6、文件的当前位移,若返回-1则出错。,.,15,4、示例,【例6-2】创建一新文件,然后对此文件进行读写操作。 设计思路与分析: (1)创建新文件 (2)将指定内容写进文件 (3)读取文件内容 (4)关闭文件,.,16,6.2 进程与进程控制,.,17,6.2.1 进程,.,18,1、什么是进程,进程是一个具有独立功能的程序的一次动态执行过程。简言之,进程就正在执行的程序。 例如,打开一个Windows资源管理器是在执行一个进程,运行一个浏览器阅读WEB网页也是在执行一个进程等。 进程与程序是两个不同的概念,程序是永久的、静态的,进程是暂时的、动态的。进程的组成包括程序、数据和进程控制块(即进程
7、状态信息)。一个程序可以多次加载到内存,成为同时运行的多个进程。,.,19,2、进程的标识,进程的标识为进程号PID。PID唯一的标识了一个进程。 PID是一个非零的正整数。通过调用函数getpid( )可以获得当前进程的PID。函数getpid( )的原型为: pid_t getpid(void); 其返回值为当前进程的进程号PID。 (返回值的数据类型pid_t 是一个宏定义,是在#include中定义的int类型)。,.,20,【例6-4】 获取当前进程的进程号PID。,1 #include 2 #include 3 int main() 4 5 printf(“PID = %d n”,
8、 getpid(); 6 return 0; 7 ,.,21,将程序保存为proID.c,使用交叉编译命令arm-linux-gcc进行交叉编译: rootlocalhost test# arm-linux-gcc -o proID proID.c 将其下载到嵌入式系统开发板上运行该程序: rootlocalhost ex5# ./proID PID = 3061 注意,每次执行结果都不一定相同。,.,22,3、创建进程,创建新进程的函数为fork( ),其函数原型为: pid_t fork(void); fork调用失败则返回-1,调用成功的返回值为进程号。 fork函数被调用后会返回两次。
9、一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。在子进程中返回0值,而在父进程中返回子进程的进程号PID。 在执行fork()之后,同一进程有两个拷贝都在运行,也就是说,子进程具有与父进程相同的可执行程序和数据(简称映像)。,.,23,【例6-5】创建一个进程。,1 #include 2 #include 3 #include 4 int main() 5 6 pid_t pid; 7 pid = fork( ); 8 printf(“PID = %d n”, pid); 9 return 0; 10 ,.,24,将程序保存为process.c,使用交叉编译命令arm-
10、linux-gcc进行交叉编译: rootlocalhost test# arm-linux-gcc -o process process.c 将其下载到嵌入式系统开发板上运行该程序: rootlocalhost ex5# ./process PID = 0 PID = 4138,从上述运行结果中可以看出fork函数的特点,概括起来就是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。第一次的返回值PID = 0是在子进程中返回的进程号,第二次的返回值PID = 4138是在父进程中返回子进程的进程号。,.,25,6.2.2 进程控制,.,26,1、调用exec函数运行
11、执行程序,为了让子进程能运行另外的执行程序,需要用到exec函数。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。 exec函数提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它取代原调用进程的数据段、代码段和堆栈段,在执行完后,原调用进程的内容除了进程号外,其他全部被新的进程替换了。也就是说,调用exec并不创建新进程,所以调用exec前后该进程的进程号PID并未改变。,.,27,2、exec函数族,在嵌入式Linux中并没有exec函数,而是有六种以exec开头的函数,统称exec函数: #
12、include int execl(const char *path, const char *arg, .); int execlp(const char *file, const char *arg, .); int execle(const char *path, const char *arg, ., char *const envp); int execv(const char *path, char *const argv); int execvp(const char *file, char *const argv); int execve(const char *path, c
13、har *const argv, char *const envp);,.,28,【例6-6】应用execlp函数列出当前目录下的所有文件。,1 #include 2 #include 3 #include 4 int main() 5 6 if (fork() = 0) 7 8 int ret; 9 /*调用execlp()函数,这里相当于调用了ls -l命令*/ 10 ret = execlp(ls, ls, -l, NULL); 11 12 return 0; 13 ,.,29,在该程序中,首先使用fork()函数创建一个子进程,然后在子进程里使用execlp()函数。从程序中可以看到,
14、这里的参数列表列出了在shell中使用的命令名和选项。 将文件保存为execlp.c,使用交叉编译命令arm-linux-gcc进行交叉编译: rootlocalhost test# arm-linux-gcc -o execlp execlp.c 将其下载到嵌入式系统开发板上运行该程序,运行结果如下所示: rootlocalhost test# ./execlp execlp execlp.c proid proid.c,.,30,3、System函数,system函数可以在一个程序的内部启动另一个程序,从而创建一个新进程。system函数所需要的头文件为: #include 其函数原型为:
15、 int system(const char *string);,.,31,4、进程调用的应用示例,【例6-8】设已有C语言的源程序Hello.c,现编写一个程序,在程序中自动编译Hello.c,并运行编译后的执行文件Hello。 1 #include 2 #include 3 #include 4 int main() 5 /* 调用system函数编译命令 */ 6 system(gcc -o Hello Hello.c);,.,32,7 printf(Hello.c Compile successfully! n); 8 if(fork( )=0) 9 10 /* 调用execlp函数执
16、行运行程序命令 */ 11 if( execlp(./Hello, Hello, NULL) 0) 12 13 printf(execlp error n); 14 15 16 sleep(1); /* 延时1秒,以等待Hello的输出结果 */ 17 printf(Hello run successfully! n); 18 ,.,33,将程序保存为comple.c,使用编译命令gcc进行编译程序: rootlocalhost test#gcc -o comple comple.c 将已经编写好的源程序Hello.c保存在同一目录下,运行comple程序,运行结果如下: rootlocalh
17、ost test# ./comple Hello.c Compile successfully! Hello! Hello run successfully!,Hello.c编译、执行后输出的结果,.,34,【例6-9】编写计算1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 的程序,将其保存到文件sum.c中,然后自动编译并运行该程序。,1 #include 2 #include 3 #include 4 #include 5 #include 6 int main() 7 ,.,35,8 int fd; 9 int len, size_r, size_w; 10
18、 char *buf = #include n int main() nnint i,s=0; n for(i=1; i=10; i+) n n s=s+i; n printf(%d=%d+%dn,s,s-i,i); n n n; 11 fd=open(sum.c, O_CREAT|O_TRUNC|O_RDWR, 0666); 12 len = strlen(buf); 13 size_w = write(fd, buf, len); 14,将buf中的程序代码写入sum.c文件,.,36,15 char *buf_r500; 16 lseek(fd,0,SEEK_SET); 17 size_
19、r = read(fd, buf_r,size_w); /察看sum.c文件内容 18 printf(size_r = %d n, size_r); 19 printf(Read: n %s n, buf_r); 20 close(fd); 21 printf(Write and Read OK! nn); 22 /编译sum.c程序 23 system(gcc -o sum sum.c); 24 printf(sum.c compiled complete. n); 25 if(fork() = 0) 26 /执行编译后的sum程序 27if(execlp(./sum, ./sum, NUL
20、L) 0) 28 29 printf(execlp error n); 30 31 32 sleep(1); 33 printf(sum run complete. n); 34 ,.,37,6.3 进程间通信,.,38,6.3.1 进程间的通信方式,图6.1 进程间通信,每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,如图6.1所示。,.,39,使用较多的进程间通信方式主要有以下几种。 (1)管道(Pipe)及有名管道(namedp
21、ipe):管道可用于具有亲缘关系进程间的通信,有名管道,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。 (2)共享内存(Sharedmemory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种通信方式需要依靠某种同步机制,如互斥锁和信号量等。 (3)消息队列(MessgeQueue):消息队列是消息的链接表,包括Posix消息队列SystemV消息队列。它克服了前两种通信方式中信息量有限的缺点,具有写权限的进程可以按照一定的规则向消息队列中添加新消息;对消息队列有读权限的进程则可以从消息队列中读取
22、消息。 (4)信号(Signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一样的。 (5)信号量(Semaphore):主要作为进程之间以及同一进程的不同线程之间的同步和互斥手段。 (6)套接字(Socket):这是一种更为一般的进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。,.,40,6.3.2 管道,管道是一种最基本的进程机制,它由pipe函数创建: #include int pipe(int fd2); 其中,数组fd2的元素为管道的两个文件描述符,管道创
23、建之后就可以直接操作这两个文件描述符。pipe函数调用成功返回0,调用失败返回-1。,.,41,管道通信的思想 :,调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个写入端一个读出端。发送进程可以源源不断的从pipe一端写入数据流,在规定的pipe文件的最大长度(如4096字节)范围内,每次写入的信息长度是可变的。接收进程在需要时可以从pipe的另一端读出数据,读出单位长度也是可变的。,.,42,管道操作的写入与读取函数: write(fd1, buf, size); 功能:把buf中的长度为size字符的消息送入管道入口fd1 fd1pipe入口 buf:存放消息的空间
24、size :要写入的字符长度 read(fd0, buf, size); fd0Pipe的出口 功能:从pipe出口fd0读出size字符的消息置入 buf中。 在用户程序,fd0指向管道的读出端,fd1指向管道的写入端。所以管道在用户程序看起来就像一个打开的文件,通过read(fd0);或者write(fd1);向这个文件读写数据其实是在读写内核缓冲区。如图6.2所示。,.,43,建立了管道之后如何实现两个进程间的通信呢?可以按下面的步骤通信。 (1)父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端。 (2)父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。
25、 (3)父进程关闭管道读端,子进程关闭管道写端。父进程可以往管道里写,子进程可以从管道里读,管道是用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通信。,.,44,【例6-10】编写一个程序,建立一个管道pipe,同时父进程生成一个子进程,子进程向pipe中写入一个字符串,父进程从pipe中读取该字符串。,1 #include 2 #include 3 int main() 4 5 int x, fd2; 6 char buf30, s30; 7 pipe(fd); 8 x = fork(); 9 if(x = 0) 10 11 sprintf(buf,This is an pi
26、pe!);,12 write(fd1, buf, 30); 13 exit(0); 14 15 else 16 17 wait(0); 18 read(fd0, s, 30); 19 printf(read: %s n, s); 20 21 ,创建管道,子进程,对字符数组buf赋值,将字符数组buf的字符串写入管道,父进程等待子进程终止,父进程从管道读取数据存放到数组s,.,45,6.3.3 共享内存,.,46,所谓共享内存,就是在内核空间开辟一块内存区域,用于多个进程之间进行交换信息,把这块内核空间的内存区域称为共享内存区。,图6.3 共享内存,.,47,实现共享内存的步骤 :,第一步是在内
27、核空间创建共享内存,也就是从内存中获得一块共享内存区域。这里需要使用函数shmget()来创建共享内存; 第二步是在进程的地址空间映射共享内存,也就是把这块创建的共享内存区域映射到进程空间中。这里需要使用的函数shmat()来映射共享内存。,.,48,共享内存的函数,调用的共享内存函数所需头文件为: #include ,.,49,1、创建共享内存区域的shmget()函数,shmget()函数用于创建共享内存区域。其函数原型为: int shmget(key_t key, int size, int flag); 函数返回值:若创建共享内存成功则返回共享内存标识符;若出错,则为 -1。 创建共
28、享内存shmget()函数的参数说明如下: (1)key参数:共享内存的键值,多个进程可以通过它访问同一个共享内存。常用一个特殊值IPC_PRIVATE,创建当前进程的私有共享内存。 (2)size参数:指定创建共享内存的大小。 (3)flag参数:操作权限,详见第3章表3.2。,.,50,【例6-10】创建一个共享内存区域。,1 #include 2 #include 3 #include 4 int main() 5 int shm_id; 6 shm_id = shmget(IPC_PRIVATE, 4096, 0666); 7 if(shm_id 0) 8 9 perror(shmge
29、t id 0 ); 10 exit(0); 11 12 printf(成功建立共享内存区域: %d n, shm_id); 13 system(ipcs -m); 14 ,创建共享内存区域,显示共享内存标识符,显示当前共享内存状况,.,51,2、建立进程空间到共享内存映射的shmat()函数,shmat( )函数用于建立进程空间地址到共享内存的映射。其函数原型为: char *shmat(int shm_id, const void *addr, int flag); 函数返回值:若映射共享内存成功则返回进程空间中被映射的区域地址;若出错,则为 -1。 建立共享内存映射shmgat()函数的参
30、数说明如下: (1)shm_id参数:要映射的共享内存标识符。 (2)addr参数:指定在调用进程中映射共享内存的地址。通常取值为0,表示由系统自动分配地址。 (3)flag参数:设置共享内存的操作权限。若取值为0,表示可对共享内存进行读写操作。,.,52,【例6-11】建立一个映射到例6-10所建共享内存的进程,并向共享内存写入数据。,1 #include 2 #include 3 #include 4 int main(int argc, char *argv) 5 int shm_id; 6 char *shm_buf; 7 shm_id = atoi(argv1); 8 shm_buf
31、=shmat(shm_id, 0, 0); 9 printf(写入数据到共享内存: n); 9 sprintf (shm_buf, 对共享内存读写操作); 10 printf(%s n, shm_buf); 11,获取要建立映射的共享内存(由命令行输入),通过映射区写入数据到共享内存,返回映射区的地址,.,53,【例6-12】建立一个从共享内存中读取数据的进程。,1 #include 2 #include 3 int main(int argc, char *argv) 4 5 int shm_id; 6 char *shm_buf, str; 7 shm_id = atoi(argv1);
32、8 shm_buf=shmat(shm_id, 0, 0); 9 printf(读取共享内存数据: n); 10 sprintf(str, shm_buf); 10 printf(%s n, str); 11 system(ipcs -m); 12 ,通过映射区读取共享内存的数据到字符数组str,.,54,3、对共享内存进行操作函数,进程与共享内存建立了映射之后,就可以在进程中对共享内存进行操作,其操作函数的原型如下: int shmctl(int shm_id, int cmd, struct shmid_ds *buf); 对共享内存操作shmctl()函数的参数说明如下: (1)shm_
33、id参数:所映射的共享内存标识符。 (2)cmd参数:指定所要进行的操作。cmd的可以取值IPC_STAT、IPC_SET、IPC_RMID、SHM_LOCK、SHM_UNLOCK。 (3)buf参数:结构体型指针 。,.,55,4、解除进程到共享内存映射的shmdt()函数,shmdt( )函数为解除进程到共享内存的映射,其函数原型为: int shmdt(const void *addr); 函数参数addr为被映射的共享内存区域的地址。 函数返回值:若解除映射成功则返回0;若出错,则为 -1。,.,56,【例6-13】解除一个进程到共享内存的映射,并释放内存空间。,1 #include
34、2 #include 3 int main(int argc, char *argv) 4 5 int shm_id; 6 char *shm_buf; 7 shm_id = atoi(argv1); 8 shm_buf=shmat(shm_id, 0, 0); 9 shmdt(shm_buf); 10 shmctl(shm_id, IPC_RMID, NULL); 11 system(ipcs -m); 12 ,定位映射地址,解除进程到共享内存的映射,释放共享内存空间,.,57,6.4 嵌入式Linux串口通信技术,.,58,6.4.1 嵌入式Linux串口通信基础,.,59,1、串口通信的
35、工作原理,所谓“串口通信”是指外设和计算机间使用一根数据信号线(另外需要地线),数据在一根数据信号线上一位一位地进行传输,每一位数据都占据一个固定的时间长度。 在串口传输中,发送方为了告诉接收方,新的数据字节分组到达,在每一个数据字节分组前面有一个起始位(通常是0),为了让接收方知道字节已经结束,在每一个数据字节分组后面有一个停止位(通常是1)。接收方一旦检测到停止位,接收方会一直等待,直到下一个开始位。,.,60,图6.4 串行传输数据的工作原理,.,61,嵌入式系统串行通信采用EIA RS-232C标准,为单向不平衡传输方式,信号电平标准12V,负逻辑,即逻辑1(MARKING)表示为信号
36、电平-12V,逻辑0(SPACING)表示为信号电平+12V,最大传送距离15米,最大传送速率19.6K波特,其传送序列如图6.1,平时线路保持为1,传送数据开始时,先发送起始位(其数据值是0),然后传8(或7,6,5)个数据位(其数据值是0,1),接着可传1位奇偶校验位,最后为12个停止位(其数据值是1),由此可见,传送一个ASCII字符(7位),加上同步信号最少需9位数据位。,.,62,2、常用信号引脚与串口通信接线,图6.5 串口的连接线,.,63,6.4.2 嵌入式Linux串口设置详解,.,64,1、起始位,通信线路上没有数据被传送时,处于逻辑“1”的状态。当发送设备要发送字符数据时
37、,首先发送一个逻辑“0”信号,这个逻辑低电平就是起始位。起始位通过通信线路传输到接收端,接收端检测到这个低电平后,就开始准备接收数据位信号。起始位所起的作用就是使通信双方同步。,.,65,2、数据位,当接收端收到起始位后,开始接收数据位。数据位的个数可以是58位。在数据传送过程中,数据位从最低有效位开始传送,接收端收到数据后,依次将其转换成并行数据。,.,66,3、奇偶校验位,数据位发送完后,为了保证数据的可靠性,还要再传送一个奇偶校验位。奇偶校验用于差错检测。如果选择偶校验,则数据位和奇偶位的逻辑“1”的个数必须为偶数,相反,如果是奇校验,数据位和奇偶位的逻辑“1”的个数为奇数。,.,67,
38、4、停止位,在奇偶位或数据位(当无奇偶校验时)之后发送停止位。停止位表示一个数据的结束。它可以是12位的低电平。接收端收到停止位后,通信线路便恢复逻辑“1”的状态,直到下一个数据的起始位到来。,.,68,5、波特率设置,通信线路上传输的位(码元)信号都必须保持一致的信号持续时间,单位时间内传送码元的数目称为波特率。 对于大多数嵌入式设备来说,其波特率都设置为115200。 在Linux中,所有的设备文件一般都位于“/dev”下,其中串口一、串口二所对应的设备名依次为“/dev/ttyS0”、“/dev/ttyS1”,可以查看在“/dev”下的文件以确认。,.,69,6.4.3RS232C标准,
39、1、电气特性 2、引脚定义,.,70,3、字符(帧)格式,RS232C采用起止式异步通信协议,其特点是一个字符接着一个字符进行传输,并且传送一个字符总是以起始位开始,以停止位结束,字符之间没有固定的时间间隔要求。其传输格式如图6.1所示,每一个字符的前面都有一位起始位(低电平,逻辑值“0”),字符本身有58位数据位,接着字符后面是一位校验码(也可以没有校验码),最后是停止位。停止位后面是不定长度的空闲位。停止位和空闲位都规定为高电平(逻辑值“1”),这样就能保证起始位开始处一定有一个下跳沿,便于接收方识别。,.,71,4、握手协议,.,72,5、双机互连方式,(1)无硬件握手情况,.,73,(
40、2)DTR和DSR握手情况,.,74,(3)RTS和CTS握手情况,.,75,6.4.4串口驱动程序的编写,一个串口驱动程序,通常包括打开串口、设置串口参数、对串口进行读写操作等内容。,.,76,1、串口操作需要的头文件,#include /*标准输入输出定义*/ #include /*标准函数库定义*/ #include /*Unix 标准函数定义*/ #include #include #include /*文件控制定义*/ #include /*终端控制定义*/ #include /*错误号定义*/,.,77,2、打开串口,通常嵌入式 Linux 系统下的串口文件是位于 /dev 下:
41、串口一 为 /dev/ttyS0; 串口二 为 /dev/ttyS1。 打开串口是通过打开函数open( ) 进行的 。 int fd;/文件描述符 fd = open( “/dev/ttyS0”, O_RDWR); /以读写方式打开串口,.,78,3、设置串口参数,最基本的串口参数设置包括波特率设置,校验位和停止位设置。,.,79,串口的设置主要是设置 struct termios 结构体的各成员值。,include struct termio unsigned short c_iflag; unsigned short c_oflag; unsigned short c_cflag; unsigned short c_lflag; unsigned char c_line; unsigned char c_ccNCC; ;,.,80,(1)波特率设置,下面是设置(或修改)波特率的代码: struct termios Opt; tcgetattr(fd, ,.,81,(2)设置校验的函数,/* *brief 设置串口数据位,停止位和校验位 *param fd 类型 int 打开的串口文件句柄 *param databits 类型 int 数据位 取值 为 7 或者8 *param stopbits 类型 int 停止
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年内蒙古自治区呼伦贝尔市林业系统人员招聘考试模拟试题及答案解析
- 2026年南通市港闸区林业系统人员招聘考试模拟试题及答案解析
- 2026年湘潭市岳塘区林业系统人员招聘考试参考试题及答案解析
- 2026年南京市玄武区广播电视台(融媒体中心)人员招聘笔试参考试题及答案解析
- 2026年四川省宜宾市林业系统人员招聘笔试模拟试题及答案解析
- 2026年宁夏回族自治区银川市广播电视台(融媒体中心)人员招聘笔试参考试题及答案解析
- 2026年山西省临汾市广播电视台(融媒体中心)人员招聘考试备考题库及答案解析
- 2026年郑州市管城回族区广播电视台(融媒体中心)人员招聘笔试备考试题及答案解析
- 2026年伊春市南岔区林业系统人员招聘笔试模拟试题及答案解析
- 小学数学五年级下册《用公倍数解决简单问题》教学设计(导学案+分层作业)
- 2026上海大歌剧院管理有限公司夏季工作人员招聘137人笔试备考题库及答案解析
- 2026江苏南京玄武区档案馆编外人员招聘1人笔试备考题库及答案解析
- 2026年广东东莞市面向村党组织书记招聘镇(街道)事业编制人员60人易考易错模拟试题(共500题)试卷后附参考答案
- 2026贵州黔西南州兴义市选聘社区工作者30人笔试参考题库及答案解析
- 高考考务人员培训系统考试试题答案
- 2026年济宁市中考物理仿真试卷(含答案解析)
- 2026上海市大数据中心招聘10名笔试参考题库及答案解析
- (二模)青岛市2026年高三年级第二次适应性检测语文试题(含答案)
- 国药集团2026届春季校园招聘笔试历年备考题库附带答案详解
- 产科孕产期管理诊疗常规
- 申万宏源社招测评题
评论
0/150
提交评论