在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

英創信息技術Linux雙進程應用示例

英創信息技術 ? 來源:英創信息技術 ? 作者:英創信息技術 ? 2020-02-06 11:34 ? 次閱讀

1、概述

一臺典型的工控設備通常包括若干通訊接口網絡、串口、CAN等),以及若干數字IO、AD通道等。運行于設備核心平臺的應用程序通過操作這些接口,實現特定的功能。通常為了高效高精度完成整個通訊控制流程,應用程序采用C/C++語言來編寫。圖1表現了典型工控設備的組成關系。

典型工控設備框圖

工控設備的另一個特點是鑒于設備大多是24小時連續運行,且無人值守,所以基本的工控設備是無顯示的。英創的工控主板ESM6800、ESM335x等都大量的應用于這類無頭工控設備之中。

在實際應用中,部分客戶需要基于已有的無頭工控設備,增加顯示界面功能,以滿足新的應用需求。顯然保持已有的基本工控處理程序不變,通過相對獨立的技術手段來實現顯示功能,最符合客戶的利益訴求。為此我們發展了一種雙進程的程序設計方案來滿足客戶的這一需求。該方案的第一個進程,以客戶已有的用C/C++寫的基礎工控進程為基礎,僅增加一個面向本地IP(127.0.0.1)的偵聽線程,用于向顯示進程提供必要的運行工況數據。圖2為增添了服務線程的工控進程:

帶有偵聽線程的基礎工控進程

方案的第二個進程則主要用于實現顯示界面,可以采用各種手段來實現,本文中介紹了使用Qt的QML語言加通訊插件的界面設計方法。第二個進程(具體是通訊插件單元)通過本地IP,以客戶端方式與基礎工控進程進行Socket通訊,完成進程間數據交換。顯示進程以及與工控進程的關系如圖3所示:

顯示進程與工控進程

2、系統設計

鑒于工業控制領域對系統運行的穩定性要求,控制系統更加傾向于將底層硬件控制部分與上層界面顯示分開,兩部分以雙進程的形式各自獨立運行。底層硬件控制部分將會監控系統硬件,管理外設等,同時收集系統的狀態;而上層界面顯示部分主要用于顯示系統狀態,并實現少量的系統控制功能,方便維護人員查看系統運行狀態并且根據當前狀態進行系統的調整。由于顯示界面不一定是所有設備都配置,而且顯示部分的程序更加復雜,從而更容易出現程序運行時的錯誤,將控制與顯示分開能夠避免由于顯示部分的程序問題而影響到整個控制系統的運行,而且沒有配置顯示屏的設備也可以直接運行底層的控制程序,增加了系統程序的兼容性。顯示與控制分離后,由于顯示界面程序不需要處理底層硬件的管理控制,在設計時可以更加注重于界面的美化,而且界面程序可以采用不同的編程語言進行開發,比如使用Qt C++或者Android java,本文將介紹基于Linux + Qt的雙進程示例程序供客戶在實際開發中參考,關于Android程序請參考我們官網的另一篇文章:《Android雙應用進程Demo程序設計》。

如上圖所示。整個系統分為控制和顯示兩個進程,底層硬件控制部分可以獨立運行,使用多線程管理不同的硬件設備,監控硬件狀態,將狀態發送給socket服務器,并且從socket服務器接收命令來更改設備狀態。Socket服務器也是一個獨立的線程,通過本地網絡通信集中處理來自硬件控制線程以及顯示程序的消息。顯示界面需要連接上socket服務器才能正確的顯示設備的狀態,同時提供必須的人工控制接口,供設備使用過程中人為調整設備運行狀態。目前在ESM6802工控主板上,界面程序可以采用Qt C++編寫,也可以使用Android java進行開發,本文僅介紹采用Qt的界面程序。顯示程序界面用QML搭建,與底層通信的部分用獨立的Qt QML插件實現,這樣顯示部分進一部分離為數據處理和界面開發,使得界面設計可以更加快捷。程序的整體界面效果如下圖所示:

目前我們只提供了串口(SERIAL)和GPIO兩部分的例程。下面將集中介紹程序中通過本地IP實現兩個進程通信的部分供客戶在實際開發中參考。

3、控制端C程序

控制端程序主要分為兩個部分,一個部分用于控制具體的硬件運行(下文稱為控制器),另一個部分為socket服務器,用于與顯示程序之間進行通信。由于本方案主要是為了展示在已有控制程序的基礎上,增加顯示界面功能,以滿足新的應用需求,所以我們在此重點介紹在已有控制程序中加入socket服務器的部分,不再詳細介紹各硬件的具體控制的實現。

增加本地IP通信的功能,首先需要在控制進程中新加入一個socket服務器線程,用于消息的集中管理,實現底層硬件與上層的界面程序的信息交換,socket服務器線程運行的函數體代碼如下:

staticvoid*_init_server(void*param)
{
intserver_sockfd, client_sockfd;
intserver_len;
structsockaddr_inserver_address;
structsockaddr_inclient_address;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");//通過本地ip通信
server_address.sin_port = htons(9733);
server_len =sizeof(server_address);
bind(server_sockfd, (structsockaddr*)&server_address, server_len);
listen(server_sockfd, 5);
intres;
pthread_t client_thread;
pthread_attr_t attr;
charid[4];
client_element*client_t;
while(1)
{
if(!client_has_space(clients))
{
printf("to many client, wait for one to quit...\n");
sleep(2);
continue;
}
printf("server waiting\n");
client_sockfd = accept(server_sockfd, (structsockaddr*)&client_address, (socklen_t *)&server_len);
//get and save client id
read(client_sockfd, &id, 4);
if((id[0]!='I') && (id[1]!='D'))
{
printf("illegal client id, drop it\n");
close(client_sockfd);
continue;
}
client_t = accept_client(clients, id, client_sockfd);
printf("client: %s connected\n", id);
//create a new thread to handle this connection
res = pthread_attr_init(&attr);
if( res!=0 )
{
printf("Create attribute failed\n");
}
//設置線程綁定屬性
res = pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );
//設置線程分離屬性
res += pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
if( res!=0 )
{
printf("Setting attribute failed\n");
}
res = pthread_create( &client_thread, &attr,
(void*(*) (void*))socked_thread_func, (void*)client_t );
if( res!=0 )
{
close( client_sockfd );
del_client(clients, client_sockfd);
continue;
}
pthread_attr_destroy( &attr );
}
}

此函數創建一個socket用于監聽(listen)等待顯示程序連接,當接受(accept)一個連接之后創建一個新的線程用于消息處理,主要用于維護socket連接的狀態,解析消息的收發方,并將消息轉送到對應的接收方,在顯示程序建立連接之前或者連接斷開之后,控制器發送的消息將不會進行發送了,而控制器依然在正常運行,用于處理消息的新線程如下:

staticvoid*socked_thread_func(void*p)
{
client_element*client_p = (client_element*)p;
printf("started socked_thread_func for client: %s\n", client_p->id);
fd_set fdRead;
intret, lenth;
structtimeval aTime;
structmsg_headmsg_h;
char*buf = (char*)&msg_h;//from:2 char to 2 char msglenth:1 int
buf[0] = client_p->id[2];
buf[1] = client_p->id[3];
charmsg[100];
client_element*send_to;
structtcp_infoinfo;
inttcp_info_len=sizeof(info);
while(1)
{
FD_ZERO(&fdRead);
FD_SET(client_p->sockfd, &fdRead);
aTime.tv_sec = 2;
aTime.tv_usec = 0;
getsockopt(client_p->sockfd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&tcp_info_len);
if(info.tcpi_state == 1)
{
//printf("$$$%d tcp connection established...\n", client_p->sockfd);
;
}
else
{
printf("$$$%d tcp connection closed...\n", client_p->sockfd);
break;
}
ret = select( client_p->sockfd+1,&fdRead,NULL,NULL,&aTime );
if(ret > 0)
{
//判斷是否讀事件
if(FD_ISSET(client_p->sockfd, &fdRead))
{
//data available, so get it!
lenth = read( client_p->sockfd, buf+2, 6 );
if( lenth != 6 )
{
continue;
}
//對接收的數據進行處理,這里為簡單的數據轉發
lenth = read(client_p->sockfd, msg, msg_h.lenth);
if(lenth == msg_h.lenth)
{
send_to = find_client(clients, msg_h.to);
//printf("try to send to client %s\n", msg_h.to);
if(send_to == NULL)
{
printf("can't find target client\n");
continue;
}
write(send_to->sockfd, &msg_h,sizeof(structmsg_head));
write(send_to->sockfd, msg, lenth);
}
//處理完畢
}
}
}
close( client_p->sockfd);
del_client(clients, client_p->sockfd);
pthread_exit( NULL );
}

這里收到消息后就解析消息頭,發送到指定的端口去(控制器或者顯示進程),由于實際應用中socket傳送數據可能存在分包的情況,客戶需要自行定義消息的數據格式來保證數據的完整性,以及對數據進行更嚴格的驗證。

另一方面對于已有的控制器來說,需要在原來的基礎上進行修改,在主線程中與socket服務器建立連接:

sockedfd= socket(AF_INET,SOCK_STREAM,0);
address.sin_family=AF_INET;
address.sin_addr.s_addr= inet_addr("127.0.0.1");
address.sin_port= htons(9733);
len =sizeof(address);
do
{
res = connect(sockedfd, (structsockaddr*)&address, len);
if(res == -1)
{
perror("oops:connecterror");
}
}while(res == -1);
write(sockedfd,"IDG1",4);
printf("###connectedtoserver\n");

然后建立兩個線程分別處理數據(data_thread_func)和命令(command_thread_func),其中data_thread_func用于監聽硬件狀態,并且發送相應的狀態消息給socket服務器,而command_thread_func用于監聽socket服務器的消息等待命令,用于改變硬件運行狀態,不需要界面帶有控制功能的客戶可以不實現commad_thread_func。以GPIO控制器為例:

void*gpio_controller::data_thread_func(void* lparam)
{
gpio_controller *pSer = (gpio_controller*)lparam;
fd_set fdRead;
intret=0;
structtimeval aTime;
unsignedintpinstates = 0;
structmsg_head buf_h;
while( 1 )
{
FD_ZERO(&fdRead);
FD_SET(pSer->interface_fd,&fdRead);
aTime.tv_sec = 2;
aTime.tv_usec = 0;
//等待硬件消息,這里是GPIO狀態改變
ret = select( pSer->interface_fd+1,&fdRead,NULL,NULL,&aTime );
if(ret < 0 )
{
//關閉
perror("select wrong");
pSer->close_interface(pSer->interface_fd);
break;
}
else
{
//select超時或者GPIO狀態發生了改變,讀取GPIO狀態,發送給socket服務器
pinstates = INPINS;
ret = GPIO_PinState(pSer->interface_fd, &pinstates);
if(ret < 0)
{
printf("GPIO_PinState::failed %d\n", ret);
break;
}
sprintf((char*)&buf_h.to[0],"D1");
buf_h.lenth =sizeof(pinstates);
write(pSer->sockedfd, (void*)&buf_h.to[0], 6);
write(pSer->sockedfd, (void*)&pinstates,sizeof(pinstates));
}
}
printf("ReceiveThreadFunc finished\n");
pthread_exit( NULL );
}
void*gpio_controller::command_thread_func(void* lparam)
{
gpio_controller *pSer = (gpio_controller*)lparam;
fd_set fdRead;
intret, len;
structtimeval aTime;
structoutcom{
unsignedintoutpin;
unsignedintoutstate;
};
structoutcomout;
structmsg_head buf_h;
while( 1 )
{
FD_ZERO(&fdRead);
FD_SET(pSer->sockedfd,&fdRead);
aTime.tv_sec = 3;
aTime.tv_usec = 300000;
//等待socket服務器的消息
ret = select( pSer->sockedfd+1,&fdRead,NULL,NULL,&aTime );
if(ret < 0 )
{
//關閉
pSer->close_interface(pSer->interface_fd);
break;
}
if(ret > 0)
{
//判斷是否讀事件
if(FD_ISSET(pSer->sockedfd,&fdRead))
{
len = read(pSer->sockedfd, &buf_h,sizeof(buf_h));
//獲取socket服務器發送的信息,進行解析
if(len !=sizeof(structoutcom))
{
printf("###invalid command lenth: %d, terminate\n", len);
}
len = read(pSer->sockedfd, &out, buf_h.lenth);
//write command
switch(out.outstate)
{
case0:
GPIO_OutClear(pSer->interface_fd, out.outpin);
if(ret < 0)
printf("GPIO_OutClear::failed %d\n", ret);
//printf("GPIO_OutClear::succeed %d\n", ret);
break;
case1:
GPIO_OutSet(pSer->interface_fd, out.outpin);
if(ret < 0)
printf("GPIO_OutSet::failed %d\n", ret);
//printf("GPIO_OutSet::succeed %d\n", ret);
break;
default:
printf("###wrong gpio state %d, no operation\n", out.outstate);
ret = -1;
break;
}
if(ret < 0)
break;
}
}
}
printf("ReceiveThreadFunc finished\n");
pthread_exit( NULL );
}

這里兩個函數主要任務都是處理數據,data_thread_func使用select函數來等待輸入GPIO的狀態改變事件,如果有狀態改變或者select等待超時都讀取一次GPIO的狀態,然后發送給socket服務器;command_thread_func監聽服務器的消息,收到消息后進行解析,然后根據消息來操作GPIO輸出信號

通過這兩個函數便與socket服務器建立了消息溝通通道,而socket服務器會自動將數據轉發到顯示進程,這種實現可以使得對已有程序的改動降到很低的程度。實際實現中,可以在socket服務器中增加狀態機等其他功能,記錄硬件狀態信息等。

4、顯示程序

顯示部分我們采用Qt來搭建,主要分為QML搭建的界面以及Qt c++編寫的數據處理插件。QML是Qt提供的一種描述性的腳本語言,類似于css,可以在腳本里創建圖形對象,并且支持各種圖形特效,以及狀態機等,同時又能跟Qt寫的C++代碼進行方便的交互,使用起來非常方便。采用QML加插件的方式主要是為了將界面設計與程序邏輯解耦,一般的系統開發中界面設計的變動往往多于后臺邏輯,因此采用QML加插件的方式將界面設計與邏輯分離有利于開發人員的分工,加速產品迭代速度,降低后期維護成本。而且QML解釋性語言的特性使得其語法更加簡單,可以將界面設計部分交給專業的設計人員開發,而不要求設計人員會c++等編程語言。Qt底層對QML做了優化,將會優先使用硬件圖形加速器進行界面的渲染,也針對觸摸屏應用做了優化,使用QML能夠更簡單快捷的搭建流暢、優美的界面。QML也支持嵌入Javascript處理邏輯,但是底層邏輯處理使用Qt C++編寫插件,能夠更好的控制數據結構,數據處理也更加高效,Qt提供了多種方式將C++數據類型導入QML腳本中,更多詳細資料可以查看Qt官方的文檔。由于篇幅原因,我們在另外一篇文章:《使用QML進行界面開發》中更詳細地介紹了QML及插件的實現,在此我們還是集中介紹socket消息處理部分。

本例程中數據處理插件的任務就是連接socket服務器,與服務器進行通信,接收消息進行解析然后提供給QML界面,以及從QML界面獲取消息給socket服務器發送命令。插件中通過socket進行通信的部分代碼如下:

voidMsgClient::cServer(void* param)
{
MsgClient*client = (MsgClient*)param;
intret;
intlen;
structsockaddr_inaddress;
intsockedfd = socket(AF_INET,SOCK_STREAM,0);
printf("sockedfd:%d\n", sockedfd);
client->sockedfd= sockedfd;
address.sin_family=AF_INET;
address.sin_addr.s_addr= inet_addr("127.0.0.1");//本地IP通信
address.sin_port= htons(9733);
len =sizeof(address);
do
{
printf("Client:connecting...\n");
ret = ::connect(sockedfd, (structsockaddr*)&address, len);//建立連接
if(ret == -1)
{
perror("oops:connecttoservererror");
}
sleep(2);
}while(ret == -1);
write(sockedfd,"IDD1",4);
printf("Client:connectedtoserver\n");
emitclient->serverConnected();
fd_setfdRead;
structtimevalaTime;
charbuf[100];
unsignedintpinstates;
structmsg_headbuf_h;
while(!client->exit_flag)
{
FD_ZERO(&fdRead);
FD_SET(sockedfd, &fdRead);
aTime.tv_sec=3;
aTime.tv_usec=0;
ret = select(sockedfd+1, &fdRead,NULL,NULL, &aTime);//等待消息
if(ret {
perror("sometingwrongwithselect");
}
if(ret >0)
{
if(FD_ISSET(sockedfd, &fdRead))
{
len = read(sockedfd, &buf_h,sizeof(buf_h));
inti;
switch(buf_h.from[0]) {//解析消息
case'S':
//串口信息
i = buf_h.from[1] -'0';
len = read(sockedfd, buf, buf_h.lenth);
client->rmsgQueue[i] << buf;
if(i == client->m_interface)
emitclient->newMsgRcved();
memset(buf,0,sizeof(buf));
break;
case'G':
//GPIO信息
len = read(sockedfd, &pinstates, buf_h.lenth);
printf("getGPIOpinstates\n");
client->updateGPIOState(pinstates);
break;
default:
break;
}
}
}
}
close(sockedfd);
pthread_exit(NULL);
}

如代碼所示,插件首先通過本地IP127.0.0.1與socket服務器建立連接(connect),然后等待socket服務器的消息(select),收到消息后進行解析,判斷是哪個硬件控制器發送的消息,然后更新相應的顯示界面,這里的代碼相對簡單,只是為了展示通過本地IP實現顯示進程與控制進程之間的通信,實際使用中客戶需要對數據進行更嚴格的檢驗。

使用QML搭建串口控制界面如下圖所示:

GPIO控制器的顯示效果如下:

由于篇幅原因,我們在此不詳細介紹實現界面的QML腳本了,將會在另一篇文章中進行專門的介紹,感興趣的用戶可以關注我們官網上的文章更新,或者向我們要取程序源碼。用戶在實際開發中可以參考此方式實現顯示進程與控制進程之間的通信,從而實現單獨的顯示進程,對已有的控制進程的更改控制到很小的程度,一方面減少了由于程序修改而造成控制程序的不穩定,另一方面使用QML又能快速的搭建界面,解決顯示設備狀態的需求。

5、總結

實際測試過程中,我們在ESM6802工控板上運行本文介紹的程序,底層控制程序直接可以開機后臺運行,顯示程序開機后手動加載,通過本地IP地址與控制程序的socket服務器連接,然后實時更新系統狀態,也能及時響應人工控制,如改變輸出GPIO的輸出狀態,關掉顯示程序之后,控制程序繼續正常運行,之后還可以再次啟動顯示程序。

將底層控制與顯示分開后,程序開發分工可以更加細致,也一定程度上增加了控制系統的穩定性,減小了維護成本。同時使用QML進行界面開發能夠更加方便快速的更新系統的顯示效果,完成產品迭代。由于底層控制與顯示之間采用socket進行通信,顯示部分也可以采用其他的開發環境,比如ESM6802也支持Android開發,用戶在產品升級換代的時候就能夠直接沿用底層控制部分的程序,而只對上層顯示部分的程序進行調整。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式主板
    +關注

    關注

    7

    文章

    6087

    瀏覽量

    35661
  • 安卓
    +關注

    關注

    5

    文章

    2139

    瀏覽量

    57689
收藏 人收藏

    評論

    相關推薦

    龍芯中科榮獲2024年度信息技術應用創新工作委員會卓越貢獻成員單位

    近日,中國電子工業標準化技術協會信息技術應用創新工作委員會(以下簡稱“信工委會”)在北京召開2024年度工作總結座談會暨信“大比武”總結大會。中國工程院院士、信
    的頭像 發表于 01-23 10:50 ?203次閱讀

    芯盛智能榮獲2024年信息技術應用創新工作委員會卓越貢獻成員單位

    日前,中國電子工業標準化技術協會信息技術應用創新工作委員會(以下簡稱 “信工委會”)2024 年度總結座談會于北京隆重舉行。此次會議對在信工作中作出突出貢獻的成員單位予以表彰。江蘇
    的頭像 發表于 01-20 09:56 ?186次閱讀

    飛騰助力首屆教育信息技術應用創新大賽圓滿落幕

    近日,由中國教育技術協會主辦,教育部教育管理信息中心教育信實驗室、公安部第三研究所、中國電子工業標準化技術協會信工委會支持,北京航空航天
    的頭像 發表于 12-24 09:57 ?224次閱讀

    有方科技參編的信息技術團體標準發布

    近日,有方科技參編的《信息技術產品供應鏈成熟度 共性指標 第1部分:企業背景評價》《信息技術產品供應鏈成熟度 共性指標 第2部分:技術掌控評價》《信息技術產品供應鏈成熟度 共性指標 第
    的頭像 發表于 12-23 10:44 ?259次閱讀

    龍芯中科助力2024首屆教育信息技術應用創新大賽成功舉辦

    近日,2024首屆教育信息技術應用創新大賽在北京航空航天大學成功舉辦。本次大賽由中國教育技術協會主辦,教育信實驗室、公安部第三研究所、中國電子工業標準化技術協會信
    的頭像 發表于 12-19 17:02 ?293次閱讀

    拓維信息參與牽頭組建!長沙新一代信息技術產教聯合體正式獲批

    的長沙新一代信息技術產教聯合體成功獲批,為長沙市信息技術產業發展注入了新的活力。圖/《2024年長沙市市級市域產教聯合體名單》長沙新一代信息技術產教聯合體將依托龍頭企
    的頭像 發表于 12-07 01:06 ?501次閱讀
    拓維<b class='flag-5'>信息</b>參與牽頭組建!長沙新一代<b class='flag-5'>信息技術</b>產教聯合體正式獲批

    一文搞懂Linux進程的睡眠和喚醒

    一、常見的進程狀態與理解 在操作系統內部,有專門用來管理進程的結構體,叫做struct task_struct,也稱作進程控制塊(PCB),主要包含描述進程的相關
    發表于 11-04 15:15

    中科達榮獲2024年軟件和信息技術服務優秀企業

    及前百家企業”名單。中科達憑借非凡的技術實力與持續的創新能力,成功入選“2024年度軟件和信息技術服務競爭力百強企業”以及“2024年軟件和信息技術服務優秀企業”。
    的頭像 發表于 10-30 11:44 ?566次閱讀

    Linux用戶身份與進程權限詳解

    在學習 Linux 系統權限相關的主題時,我們首先關注的基本都是文件的 ugo 權限。ugo 權限信息是文件的屬性,它指明了用戶與文件之間的關系。但是真正操作文件的卻是進程,也就是說用戶所擁有的文件
    的頭像 發表于 10-23 11:41 ?439次閱讀
    <b class='flag-5'>Linux</b>用戶身份與<b class='flag-5'>進程</b>權限詳解

    國產化背景下的工控主板發展現狀

    ,是信息技術應用創新產業的簡稱,于2016年“信工委會”(信息技術應用創新工作委員會)提出,目的就是要推動我們國內軟硬件關鍵技術的研發
    的頭像 發表于 09-21 16:15 ?534次閱讀

    梯度科技入選2023年信息技術應用創新解決方案名單

    日前,工業和信息化部網絡安全產業發展中心(工業和信息化部信息中心)在天津舉辦2024信息技術應用創新發展大會暨解決方案應用推廣大會。會上正式公布了2023年
    的頭像 發表于 09-09 16:29 ?506次閱讀

    中軟國際信服務助力大連信產業發展

    為進一步激發大連本地信產業生態的活力與潛力,搭建一個高效、開放的交流平臺。由大連軟件行業協會攜手大連市信息技術應用創新綜合服務中心主辦,中軟國際協辦的,2024年大連市信息技術應用創新產業發展大會
    的頭像 發表于 08-27 16:49 ?980次閱讀

    深入探討Linux進程調度器

    Linux操作系統作為一個開源且廣泛應用的操作系統,其內核設計包含了許多核心功能,而進程調度器(Scheduler)就是其中一個至關重要的模塊。進程調度器負責決定在任何給定的時刻哪個進程
    的頭像 發表于 08-13 13:36 ?1007次閱讀
    深入探討<b class='flag-5'>Linux</b>的<b class='flag-5'>進程</b>調度器

    龍芯中科三項信方案入圍工信部2023年信息技術應用創新應用示范案例名單

    近日,工業和信息化部通報了2023年信息技術應用創新解決方案征集遴選結果,本次共評選出典型解決方案173個、應用示范案例83個、單項創新案例64個。
    的頭像 發表于 03-07 16:45 ?1037次閱讀
    龍芯中科三項信<b class='flag-5'>創</b>方案入圍工信部2023年<b class='flag-5'>信息技術</b>應用創新應用示范案例名單

    RX78M組 EtherCAT ETG.5003示例程序固件信息技術

    電子發燒友網站提供《RX78M組 EtherCAT ETG.5003示例程序固件信息技術.pdf》資料免費下載
    發表于 02-21 14:22 ?1次下載
    RX78M組  EtherCAT ETG.5003<b class='flag-5'>示例</b>程序固件<b class='flag-5'>信息技術</b>
    主站蜘蛛池模板: 激情五月婷婷综合网 | 欧美视频综合 | 天堂tv亚洲tv日本tv欧美人tv | 久久久精品2021免费观看 | 亚洲国产欧美精品一区二区三区 | 1000又爽又黄禁片 | 国产乱码免费卡1卡二卡3卡四 | 特黄一级大片 | 永久福利盒子日韩日韩免费看 | 中文字幕国产一区 | www.成人在线| 欧美三级 欧美一级 | 在线免费观看一区二区三区 | 欧美在线bdsm调教一区 | 欧美色视频日本 | 欧美人成一本免费观看视频 | www.五月婷婷.com | 黄视频福利 | 男人午夜天堂 | 亚洲 午夜在线一区 | 午夜视| 亚洲天堂视频在线观看免费 | 天堂网在线最新版www | 国产精品爽爽影院在线 | 一级一片免费视频播放 | 黄色精品视频 | 午夜爱爱小视频 | 国产精品美女免费视频观看 | 欧美综合在线视频 | 手机在线免费观看视频 | 国产h视频在线 | 国产午夜精品久久久久免费视 | 久久69| 欧美图片小说视频 | 男人天堂色男人 | 日本高清免费一本视频在线观看 | 日日爽夜夜 | 日韩高清性爽一级毛片免费 | 亚洲图片综合区另类图片 | 香蕉视频色版在线观看 | 亚洲色图欧美色 |