使用Windows API进行串口编程

 

串口通信一般分为四大步:打开串口->配置串口->读写串口->关闭串口,还可以在串口上监听读写等事件。
1、打开和关闭串口
Windows中串口是作为文件来处理的,调用CreateFile()函数可以打开串口,函数执行成功返回串口句柄,出错返回INVALID_HANDLE_VALUE。

  1. HANDLE WINAPI CreateFile(
  2. _In_ LPCTSTR lpFileName,//要打开或创建的文件名
  3. _In_ DWORD dwDesiredAccess,//访问类型
  4. _In_ DWORD dwShareMode,//共享方式
  5. _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,//安全属性
  6. _In_ DWORD dwCreationDisposition,//指定要打开的文件已存在或不存在的动作
  7. _In_ DWORD dwFlagsAndAttributes,//文件属性和标志
  8. _In_opt_ HANDLE hTemplateFile//一个指向模板文件的句柄
  9. );

lpFileName:要打开或创建的文件名。
dwDesiredAccess:访问方式。0为设备查询访问方式;GENERIC_READ为读访问;GENERIC_WRITE为写访问; 
dwShareMode:共享方式。0表示文件不能被共享,其它打开文件的操作都会失败;FILE_SHARE_READ表示允许其它读操作;FILE_SHARE_WRITE表示允许其它写操作;FILE_SHARE_DELETE表示允许其它删除操作。 
lpSecurityAttributes:安全属性。一个指向SECURITY_ATTRIBUTES结构的指针。 
dwCreationDisposition:创建或打开文件时的动作。 OPEN_ALWAYS:打开文件,如果文件不存在则创建它;TRUNCATE_EXISTING 打开文件,且将文件清空(故需要GENERIC_WRITE权限),如果文件不存在则会失败;OPEN_EXISTING打开 文件,文件若不存在则会失败;CREATE_ALWAYS创建文件,如果文件已存在则清空;CREATE_NEW创建文件,如文件存在则会失败;
dwFlagsAndAttributes:文件标志属性。FILE_ATTRIBUTE_NORMAL常规属性; FILE_FLAG_OVERLAPPED异步I/O标志,如果不指定此标志则默认为同步IO;FILE_ATTRIBUTE_READONLY文件为只读; FILE_ATTRIBUTE_HIDDEN文件为隐藏。FILE_FLAG_DELETE_ON_CLOSE所有文件句柄关闭后文件被删除;其它标志和属性参考MSDN。
hTemplateFile:一个文件的句柄,且该文件必须是以GENERIC_READ访问方式打开的。如果此参数不是NULL,则会使用hTemplateFile关联的文件的属性和标志来创建文件。如果是打开一个现有文件,则该参数被忽略。
使用CreateFile()打开串口时需要注意的是:lpFileName文件名直接写串口号名,如“COM1”,COM10及以上的串口名格式应为:"\\\\.\\COM10";dwShareMode共享方式应为0,即串口应为独占方式;dwCreationDisposition打开时的动作应为OPEN_EXISTING,即串口必须存在。
调用CloseHandle()函数来关闭串口,函数参数为串口句柄。

  1. BOOL WINAPI CloseHandle(HANDLE hObject);

2、配置串口
设置超时
在调用ReadFile()和WriteFile()读写串口的时候,如果没有指定异步操作的话,读写都会一直等待指定大小的数据,这时候我们可能想要设置一个读写的超时时间。调用SetCommTimeouts()可以设置串口读写超时时间,GetCommTimeouts()可以获得当前的超时设置,一般先利用GetCommTimeouts获得当前超时信息到一个COMMTIMEOUTS结构,然后对这个结构自定义,再调用SetCommTimeouts()进行设置。

  1. BOOL GetCommTimeouts(
  2. _In_ HANDLE hFile,
  3. _Out_ LPCOMMTIMEOUTS lpCommTimeouts
  4. );
  5. BOOL SetCommTimeouts(
  6. _In_ HANDLE hFile,
  7. _In_ LPCOMMTIMEOUTS lpCommTimeouts
  8. );
  1. typedef struct _COMMTIMEOUTS {
  2. DWORD ReadIntervalTimeout; /* Maximum time between read chars. */
  3. DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */
  4. DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */
  5. DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */
  6. DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */
  7. } COMMTIMEOUTS,*LPCOMMTIMEOUTS;

ReadIntervalTimeout为读操作时两个字符间的间隔超时,如果两个字符之间的间隔超过本限制则读操作立即返回。
ReadTotalTimeoutMultiplier为读操作在读取每个字符时的超时。
ReadTotalTimeoutConstant为读操作的固定超时。
WriteTotalTimeoutMultiplier为写操作在写每个字符时的超时。
WriteTotalTimeoutConstant为写操作的固定超时。
以上各个成员设为0表示未设置对应超时。
超时设置有两种:间隔超时和总超时,间隔超时就是ReadIntervalTimeout,总超时= ReadTotalTimeoutConstant + ReadTotalTimeoutMultiplier*要读写的字符数。
可以看出:间隔超时和总超时的设置是不相关的,写操作只支持总超时,而读操作两种超时均支持。
比如:
ReadTotalTimeoutMultiplier设为1000,其余成员为0,如果ReadFile()想要读取5个字符,则总的超时时间为1*5=5秒;
ReadTotalTimeoutConstant设为5000,其余为0,则总的超时时间为5秒;
ReadTotalTimeoutMultiplier设为1000并且ReadTotalTimeoutConstant设为5000,其余为0,如果ReadFile()想要读取5个字符,则总的超时间为1*5+5 =10秒。 
ReadIntervalTimeout设为MAXDWORD,ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则读操作会一次读入缓冲区的内容后立即返回,不管是否读入了指定字符。
需要注意的是,用重叠方式读写串口时,SetCommTimeouts()仍然是起作用的,在这种情况下,超时规定的是I/O操作的完成时间,而不是ReadFile和WriteFile的返回时间。

设置发送和接收缓冲区大小
SetupComm()函数用来设置串口的发送/接受缓冲区的大小,如果通信的速率较高,则应该设置较大的缓冲区。

  1. BOOL WINAPI SetupComm(
  2. __in HANDLE hFile,//串口句柄
  3. __in DWORD dwInQueue,//输入缓冲区大小
  4. __in DWORD dwOutQueue//输出缓冲区大小
  5. );

设置串口的配置信息
函数GetCommState()和SetCommState()分别用来获得和设置串口的配置信息,如波特率、校验方式、数据位个数、停止位个数等。一般也是先调用GetCommState()获得串口配置信息到一个DCB结构中去,在对这个结构自定义后调用SetCommState()进行设置。

  1. BOOL WINAPI GetCommState(
  2. __in HANDLE hFile,//串口句柄
  3. __out LPDCB lpDCB//保存的串口配置信息
  4. );
  5.  
  6. BOOL WINAPI SetCommState(
  7. __in HANDLE hFile,//串口句柄
  8. __in LPDCB lpDCB//设置的串口配置信息
  9. );

DCB结构中几个比较重要的成员有:BaudRate(波特率)、fParity(指定奇偶校验使能)、Parity(校验方式)、ByteSize(数据位个数)、StopBits(停止位个数)。
BaudRate波特率常用的有CBR_9600、CBR_14400、CBR_19200、CBR_38400、CBR_56000、CBR_57600、CBR_115200、 CBR_128000、 CBR_256000。
fParity指定奇偶校验使能,若此成员为1,允许奇偶校验。
Parity校验方式可以为0~4,对应宏为NOPARITY、ODDPARITY、EVENPARITY、MARKPARITY、SPACEPARITY,分别表示无校验、奇校验、偶校验、校验置位(标记校验)、校验清零。
ByteSize数据位个数可以为5~8位。
StopBits停止位可以为0~2,对应宏为ONESTOPBIT、ONE5STOPBITS、TWOSTOPBITS,分别表示1位停止位、1.5位停止位、2位停止位。

读写串口
清空缓冲
PurgeComm()函数用来停止读写操作、清空读写缓冲区,第一次读取串口数据、写串口数据之前、串口长时间未使用、串口出现错误等情况下,应先清空读或写缓冲区。

  1. BOOL PurgeComm(HANDLE hFile, DWORD dwFlags );

第二个参数dwFlags指定串口执行的动作,可以是以下值的组合:
-PURGE_TXABORT:停止目前所有的传输工作立即返回不管是否完成传输动作。 
-PURGE_RXABORT:停止目前所有的读取工作立即返回不管是否完成读取动作。 
-PURGE_TXCLEAR:清除发送缓冲区的所有数据。 
-PURGE_RXCLEAR:清除接收缓冲区的所有数据。
如清除串口的所有操作和缓冲:PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);

清除错误
ClearCommError()用来清除通信中的错误及获得当前通信状态。在读写操作之前,可以调用ClearCommError来清除错误和获得缓冲区内数据大小。

  1. BOOL WINAPI ClearCommError(
  2. _In_ HANDLE hFile,//串口句柄
  3. _Out_opt_ LPDWORD lpErrors,//返回的错误码
  4. _Out_opt_ LPCOMSTAT lpStat//返回的通讯状态
  5. );

lpErrors用来保存错误码,具体对应的什么错误为:
1-CE_BREAK:检测到中断信号。意思是说检测到某个字节数据缺少合法的停止位。 
2-CE_FRAME:硬件检测到帧错误。 
3-CE_IOE:通信设备发生输入/输出错误。 
4-CE_MODE:设置模式错误,或是hFile值错误。 
5-CE_OVERRUN:溢出错误,缓冲区容量不足,数据将丢失。 
6-CE_RXOVER:溢出错误。 
7-CE_RXPARITY:硬件检查到校验位错误。 
8-CE_TXFULL:发送缓冲区已满。

lpStat为指向_COMSTAT结构的指针,保存通讯状态。一般我们只关心这个结构中的两个成员:cbInQue、cbOutQue,分别表示输入缓冲区中的字节数、输出缓冲区中的字节数。

读写串口数据
调用WriteFile()向串口中写数据,ReadFile()从串口读数据,函数执行成功返回TRUE,失败返回FALSE。
需要注意的有两点:
如果想要异步读写操作,则lpOverlappen参数不能为NULL,而且在CreateFile()打开文件时应指定FILE_FLAG_OVERLAPPEN标记。在异步读写操作的时候,ReadFile()和WriteFile()返回FALSE时应调用GetLastError函数分析返回的结果,如果是ERROR_IO_PENDING,这说明异步I/O操作正在进行。
在用ReadFile()读文件时,如果想要读取的数据大小比文件内容大,则只会读取文件大小的数据。而读串口时,如果想要读取的数据比缓冲区中数据大,则ReadFile()会阻塞,直到数据到达或者超时。
函数WriteFileEx()与ReadFileEx()只能用于异步读写操作,而且可以设置一个读写完成后自动调用的回调函数,函数执行成功返回TRUE,表示异步I/O操作开始,出错返回FALSE。

  1. BOOL WINAPI ReadFile(
  2. _In_ HANDLE hFile,//文件句柄
  3. _Out_ LPVOID lpBuffer,//指向一个缓冲区,保存读取的数据
  4. _In_ DWORD nNumberOfBytesToRead,//要读取数据的字节数,如果实际读取的字节数小于这个数的话函数会一直等待直到超时
  5. _Out_opt_ LPDWORD lpNumberOfBytesRead,//实际读取的字节数
  6. _Inout_opt_ LPOVERLAPPED lpOverlapped//指向一个OVERLAPPED结构,用于异步操作
  7. );
  8.  
  9. BOOL WINAPI WriteFile(
  10. _In_ HANDLE hFile,//文件句柄
  11. _In_ LPCVOID lpBuffer,//指向一个缓冲区,包含要写入的数据
  12. _In_ DWORD nNumberOfBytesToWrite,//要写入数据的字节数
  13. _Out_opt_ LPDWORD lpNumberOfBytesWritten,//实际写入的字节数
  14. _Inout_opt_ LPOVERLAPPED lpOverlapped//指向一个OVERLAPPEN结构体,用于异步操作
  15. );

监听串口事件和异步读写串口
在串口编程中,可以先设置好串口所关注的事件,然后启动一个辅助线程来监听该事件是否已经发生,如果没有发生的话该线程就一直等待,当事件发生后,如读缓冲区中收到数据,该线程可以向主线程窗体发送对应事件消息提示进行读串口处理,或者在辅助线程中直接进行异步读写串口处理。SetCommMask()函数用来设置串口监听事件,GetCommMask()函数获得通信设备上的事件掩码。

  1. BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask);

参数hFile为串口句柄,dwEvtMask为要监视的串口事件掩码,可以有以下位值:
EV_RXCHAR:输入缓冲区中收到数据
EV_TXEMPTY:输出缓冲区中的数据已被完全送出
EV_RXFLAG:使用SetCommState()函数设置的DCB结构中的事件字符已被传入输入缓冲区中
。。。。。。
串口事件设置好以后可以使用WaitCommEvent()来判断事件是否已经发生。

  1. BOOL WINAPI WaitCommEvent(
  2. _In_ HANDLE hFile,
  3. _Out_ LPDWORD lpEvtMask,
  4. _In_ LPOVERLAPPED lpOverlapped
  5. );

-hFile:串口句柄 
-lpEvtMask:检测到串口通信事件的话就将其写入该参数中。 
-lpOverlapped:指向一个重叠结构,如果串口打开时指定了FILE_FLAG_OVERLAPPED标志 ,则改参数不能为NULL,且重叠结构中 应该包含一个人工重置对象句柄(通过CreateEvent()创建)。
如果不是异步读写的话,WaitCommEvent()会一直等待事件的发生,如果异步读写没有立即完成的话函数会直接返回FALSE,调用GetLastError()会返回ERROR_IO_PENDING。
目前发现了一个BUG:如果CloseHandle()关闭串口的时候,WaitCommEvent()还在等待事件,那么程序就会出现卡死现象,而且在同步读写下很容易发生这种情况。 MSDN上说如果是重叠操作的话再次调用SetCommMask()改变事件掩码将会使WaitCommEvent()立即返回,但我试了下在同步读写情况下这种方法不管用,不知道重叠操作的情况是否真的管用!

5、异步读写串口
重叠模型是异步I/O方式中一种,所以可以使用重叠操作来实现异步读写串口。前面说过,如果重叠操作不能立即完成,则WaitCommEvent()返回FALSE,GetLastError()会返回ERROR_IO_PENDING,表示操作正在后台进行,在WaitCommEvent返回之前,参数重叠结构中的hEvent成员会被设置为无信号状态,如果当事件发生或错误发生时,其被设置为有信号状态,应用程序可以调用wait functions(WaitForSingleObject、WaitForSingleObjectEx等)来判断事件对象的状态,而WaitCommEvent()的参数lpEvtMask会保存具体发生的事件。
有两种方法可以等待或者判断重叠操作是否完成,一种是使用WaitForSingleObject()来等待读写函数中OVERLAPPED类型的参数的hEvent成员:当调用ReadFile, WriteFile 函数的时候,该成员会自动被置为无信号状态;当重叠操作完成后,该成员变量会自动被置为有信号状态。
另一种方法是调用GetOverlappedResult()获得重叠操作的状态,来判断重叠操作是否完成,函数原型:

  1. BOOL WINAPI GetOverlappedResult(
  2. _In_ HANDLE hFile,//文件句柄
  3. _In_ LPOVERLAPPED lpOverlapped,//指向欲检查的重叠结构
  4. _Out_ LPDWORD lpNumberOfBytesTransferred,//返回重叠操作(读或写)的字节数
  5. _In_ BOOL bWait
  6. );

如果参数bWait为TRUE则函数会一直等待直到重叠结构中的hEvent变成有信号,即一直等到重叠操作完成;FALSE为如果检测到pending状态则立即返回,此时函数返回FALSE,GetLastError()返回值为ERROR_IO_INCOMPLETE。

下面为一个异步读写串口的示例:

  1. /******************主线程*********************/
  2.  
  3. //以重叠方式打开串口
  4. g_hCom = CreateFile(_T("COM7"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
  5. if (g_hCom == INVALID_HANDLE_VALUE)
  6. {
  7. int a = GetLastError();
  8. CString str;
  9. str.Format(_T("%d"), a);
  10. AfxMessageBox(str);
  11. return false;
  12. }
  13.  
  14. //设置读超时
  15. COMMTIMEOUTS timeouts;
  16. GetCommTimeouts(g_hCom, &timeouts);
  17. timeouts.ReadIntervalTimeout = 0;
  18. timeouts.ReadTotalTimeoutMultiplier = 0;
  19. timeouts.ReadTotalTimeoutConstant = 60000;
  20. timeouts.WriteTotalTimeoutMultiplier = 0;
  21. timeouts.WriteTotalTimeoutConstant = 0;
  22. SetCommTimeouts(g_hCom, &timeouts);
  23.  
  24. //设置读写缓冲区大小
  25. static const int g_nZhenMax = 32768;
  26. if (!SetupComm(g_hCom, g_nZhenMax, g_nZhenMax))
  27. {
  28. AfxMessageBox(_T("SetupComm() failed"));
  29. CloseHandle(g_hCom);
  30. return false;
  31. }
  32.  
  33. //设置串口配置信息
  34. DCB dcb;
  35. if (!GetCommState(g_hCom, &dcb))
  36. {
  37. AfxMessageBox(_T("GetCommState() failed"));
  38. CloseHandle(g_hCom);
  39. return false;
  40. }
  41. int nBaud = 115200;
  42. dcb.DCBlength = sizeof(DCB);
  43. dcb.BaudRate = nBaud;//波特率为115200
  44. dcb.Parity = 0;//校验方式为无校验
  45. dcb.ByteSize = 8;//数据位为8位
  46. dcb.StopBits = ONESTOPBIT;//停止位为1位
  47. if (!SetCommState(g_hCom, &dcb))
  48. {
  49. AfxMessageBox(_T("SetCommState() failed"));
  50. CloseHandle(g_hCom);
  51. return false;
  52. }
  53.  
  54. //清空缓冲
  55. PurgeComm(g_hCom, PURGE_RXCLEAR|PURGE_TXCLEAR);
  56.  
  57. //清除错误
  58. DWORD dwError;
  59. COMSTAT cs;
  60. if (!ClearCommError(g_hCom, &dwError, &cs))
  61. {
  62. AfxMessageBox(_T("ClearCommError() failed"));
  63. CloseHandle(g_hCom);
  64. return false;
  65. }
  66.  
  67. //设置串口监听事件
  68. SetCommMask(g_hCom, EV_RXCHAR);
  69.  
  70. HANDLE hThread1 = CreateThread(NULL, 0, ThreadSendMsg, NULL, 0, NULL);
  71. CloseHandle(hThread1);
  72.  
  73. /******************辅助线程********************/
  74. DWORD WINAPI ThreadSendMsg(LPVOID lpParameter)
  75. {
  76. while(1)
  77. {
  78. OVERLAPPED osWait;
  79. memset(&osWait,0,sizeof(OVERLAPPED));
  80. osWait.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  81. DWORD dwEvtMask;
  82.  
  83. if (WaitCommEvent(g_hCom, &dwEvtMask, &osWait))
  84. {
  85. if (dwEvtMask & EV_RXCHAR)
  86. {
  87. DWORD dwError;
  88. COMSTAT cs;
  89. if (!ClearCommError(g_hCom, &dwError, &cs))
  90. {
  91. AfxMessageBox(_T("ClearCommError() failed"));
  92. CloseHandle(g_hCom);
  93. return false;
  94. }
  95.  
  96. char buf[101] = {0};
  97. DWORD nLenOut = 0;
  98. DWORD dwTrans;
  99. OVERLAPPED osRead;
  100. memset(&osRead,0,sizeof(OVERLAPPED));
  101. osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  102.  
  103. BOOL bReadStatus = ReadFile(g_hCom, buf, cs.cbInQue, &nLenOut,&osRead);
  104. if(!bReadStatus)
  105. {
  106. if(GetLastError()==ERROR_IO_PENDING)//重叠操作正在进行
  107. {
  108. //GetOverlappedResult(g_hCom,&osRead2,&dwTrans,true);判断重叠操作是否完成
  109.  
  110. //To do
  111. }
  112. }
  113. else//操作已完成
  114. {
  115. //To do
  116. }
  117.  
  118. }
  119. }
  120. else
  121. {
  122. if(GetLastError()==ERROR_IO_PENDING)
  123. {
  124. WaitForSingleObject(osWait.hEvent, INFINITE);
  125. if (dwEvtMask & EV_RXCHAR)
  126. {
  127. DWORD dwError;
  128. COMSTAT cs;
  129. if (!ClearCommError(g_hCom, &dwError, &cs))
  130. {
  131. AfxMessageBox(_T("ClearCommError() failed"));
  132. CloseHandle(g_hCom);
  133. return false;
  134. }
  135.  
  136. char buf[101] = {0};
  137. DWORD nLenOut = 0;
  138. DWORD dwTrans;
  139. OVERLAPPED osRead;
  140. memset(&osRead,0,sizeof(OVERLAPPED));
  141. osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  142.  
  143. BOOL bReadStatus = ReadFile(g_hCom, buf, cs.cbInQue, &nLenOut,&osRead);
  144. if(!bReadStatus)
  145. {
  146. if(GetLastError()==ERROR_IO_PENDING)//重叠操作正在进行
  147. {
  148. //GetOverlappedResult(g_hCom,&osRead2,&dwTrans,true);判断重叠操作是否完成
  149.  
  150. //To do
  151. }
  152. }
  153. else//操作已完成
  154. {
  155. //To do
  156. }
  157.  
  158. }
  159. }
  160. }
  161. }
  162.  
  163. return 1;
  164. }

在异步编程中我发现在读事件发生后,利用ClearCommError()获得的缓冲区内数据大小有时会比对方WriteFile()指定发送的数据大小小,我猜是因为这个时候数据还没有全部发送到缓冲区内,这点需要注意。

使用Windows API进行串口编程的更多相关文章

  1. 基于C++简单Windows API的socket编程(阻塞模式)

    1. 概述:简单的基于Windows API的socket点对点聊天程序,为了方便初学者,本文代码均采用阻塞原理编写. 2. 代码样例 Server.cpp(服务端) #include <cst ...

  2. [Windows] Windows API 串口通信

    Windows 中通过Windows API 进行串口通信主要有以下步骤: 打开串口 配置串口 读写串口 关闭串口 打开串口 关键API: CreateFile Windows 中进行设备的操作,第一 ...

  3. Windows API串口编程详解

    (一)Windows API串口通信编程概述 Windows环境下的串口编程与DOS环境下的串口编程有很大不同.Windows环境下的编程的最大特征之一就是设备无关性,它通过设备驱动程序将Window ...

  4. storysnail的Windows串口编程笔记

    storysnail的Windows串口编程笔记 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据 ...

  5. windows串口编程Win32,PComm串口开发

    https://blog.csdn.net/u011430225/article/details/51496456 https://blog.csdn.net/eit520/article/detai ...

  6. Windows下串口编程

     造冰箱的大熊猫@cnblogs 2019/1/27 将Windows下串口编程相关信息进行下简单小结,以备后用. 1.打开串口 打开串口使用CreateFile()函数.以打开COM6为例: HAN ...

  7. storysnail的Linux串口编程笔记

    storysnail的Linux串口编程笔记 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据Ge ...

  8. PB串口编程资料(转)

    ----MSCOMM32参数基本介绍2008年03月29日 星期六 上午 11:37MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能.MSComm控件在串口编程时非常方便,程序 ...

  9. VS2010下MFC的串口编程

    串口通信简介 一般来说,计算机都有一个或多个串行端口,这些串口提供了外部设备与PC进行数据传输和通信的通道,在CPU和外设之间充当解释器的角色.当字符数据从CPU发送给外设时,这些字符数据将被转换成串 ...

随机推荐

  1. React中props和state相同点和不同点

    朋友们,我想死你们了,最近这几天忙着和病魔作斗争所以没怎么写博客,今天感觉好点了,赶紧来写一波,就是这木敬业. 今天我们来讨论讨论props和state相同点和不同点 首先我来概要说明一下这两者 pr ...

  2. JavaScript异步和单线程

    一,同步和异步的区别: 同步会阻塞代码执行,而异步不会.(比如alert是同步,setTimeout是异步) 二,前端使用异步的场景: 1,定时任务:setTimeout,setInterval 2, ...

  3. recovery 升级过程执行自定义shell命令

    有时候我们需要,在升级的过程中,执行一些shell命令,来完成我们的一些需求,利用升级过程,进行一些特殊化的操作,思路如下: 第一: 把我们需要执行的命令,写成一个test.sh脚本,然后在recov ...

  4. [Linux.NET]在CentOS 7.x中编译方式安装Nginx

    Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.由俄罗斯的程序设计师Igor Sysoev所开发,供俄罗斯大型的 ...

  5. GridSearchCV交叉验证

    代码实现(基于逻辑回归算法): # -*- coding: utf-8 -*- """ Created on Sat Sep 1 11:54:48 2018 @autho ...

  6. MySQL--eq_range_index_dive_limit参数学习,MYSQL 5.6 5.7处理数据分布不均的问题

    官方文档如下描述:This variable indicates the number of equality ranges in an equality comparison condition w ...

  7. sqlserver 拆分

    有表tb, 如下:id value----------- -----------1 aa,bb2 aaa,bbb,ccc欲按id,分拆value列, 分拆后结果如下:id value--------- ...

  8. MySQL之慢查询日志分析

    在MySQL命令行中查看慢查询日志是否打开了: mysql> show variables like '%slow_query%'; +---------------------------+- ...

  9. Base64编码/解码

    /// <summary> /// Base64编码 /// </summary> /// <param name="str">字符串</ ...

  10. WEB应用打成jar包全记录

    内容属原创,转载请注明出处 题外 由于项目的需求—不管是怎么产生的这个需求—总之,需要支持把一个web应用打成jar包供其他应用使用,这就有了下面的过程. 这个过程里用到了Spring和SpringM ...