linux系統編程---線程總結

線程總結

  • 1 線程的實現
    • 線程創建
    • 線程退出
    • 線程等待
    • 線程清理
  • 2 線程的屬性
    • 線程的分離
    • 線程的棧地址
    • 線程棧大小
    • 線程的調度策略
    • 線程優先級
  • 3 線程的同步
    • 互斥鎖
    • 讀寫鎖
    • 條件變量
    • 信號量

線程是系統獨立調度和分配的基本單位。同一進程中的多個線程將共享該進程中的全部系統資源,例如文件描述符和信號處理等。一個進程可以有很多線程,每個線程并發執行不同的任務。

1 線程的實現

線程創建

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
  • thread:指向線程標識符的指針,當線程創建成功后,用來返回創建的線程ID
  • att:指定線程的屬性,NULL表示默認
  • start_routine:函數指針,指向線程創建后要調用的函數,直接賦值函數名即可
  • arg是傳給函數的參數
#include  <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>void * my_pthread(void *arg)
{printf("pthread id =%ld\n",pthread_self());return NULL;
}int main(void)
{pthread_t pid;if(pthread_create(&pid,NULL,my_pthread,NULL)){printf("pthread_create error\n");exit(1);}sleep(2);return 0;
}

在這里插入圖片描述

線程退出

void pthread_exit(void *retval);
  • retval是線程結束時的返回值,可由其他函數如pthread_join來獲取

注意:如果進程中任何一個線程調用exit()或_exit()函數,那么整個進程就會終止。線程的正常退出方法有線程從線程函數中返回(return)、線程可以被另一個線程終止以及線程自己調用pthread_exit()

線程等待

在調用pthread_create函數后,就會運行相關的線程函數。pthread_join()是一個線程阻塞函數,調用后,調用者一直等待指定的線程結束才返回,被等待線程的資源就會被回收。

int pthread_join(pthread_t thread, void **retval);
  • pthread是等待結束的線程id
  • retval是用戶定義的指針,用來存儲被等待線程結束時的返回值。
#include  <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>void * my_pthread(void *arg)
{int ret =5;printf("pthread id =%ld\n",pthread_self());pthread_exit((void *)&ret);
}int main(void)
{pthread_t pid;void *ret ;if(pthread_create(&pid,NULL,my_pthread,NULL)){printf("pthread_create error\n");exit(1);}pthread_join(pid,&ret);printf("ret = %d\n",*(int * )ret);return 0;
}

線程函數運行結束是可以有返回值的,這個函數的返回值怎么返回呢?可以通過return語句進行返回,也可以通過pthread_exit()函數進行返回。函數的這個返回值怎么來接收呢?就通過pthread_join()函數來接受。
當然也可以選擇不接受該線程的返回值,只阻塞該線程:

pthread_join(tid, NULL);

線程清理

線程終止有兩種情況:正常終止和非正常終止。線程主動調用pthread_exit()或者從線程中return都使進程正常退出。非正常終止時線程在其他線程的干預下停止運行或者由于自身運行錯誤而退出。

線程可以安排它退出時需要調用的函數,這與進程在退出時可以用atexit函數安排退出函數是類似的。這樣的函數稱為線程清理處理程序。一個線程可以建立多個清理處理程序。

void pthread_cleanup_push(void (* rtn)(void *), void * arg);

函數說明:將清除函數壓入清除棧。rtn是清除函數,arg是清除函數的參數。

void pthread_cleanup_pop(int execute);

函數說明:將清除函數彈出清除棧。執行到pthread_cleanup_pop()時,參數execute決定是否在彈出清除函數的同時執行該函數,execute非0時,執行;execute為0時,不執行。

從pthread_cleanup_push的調用點到pthread_cleanip_pop之間的程序段中的終止動作(包括調用pthread_exit()和異常終止,不包括return)都將執行pthread_cleanup_push()所指定的清理函數。

int pthread_cancel(pthread_t thread);

函數說明:取消線程,該函數在其他線程中調用,用來強行殺死指定的線程。

2 線程的屬性

參考文章:

  1. https://blog.csdn.net/zsf8701/article/details/7842392
  2. https://blog.csdn.net/qq_22847457/article/details/89461222
  3. https://blog.csdn.net/yychuyu/article/details/84503261?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&utm_relevant_index=2

線程屬性標識符:pthread_attr_t 包含在 pthread.h 頭文件中。

typedef struct
{int                   detachstate;      //線程的分離狀態int                   schedpolicy;     //線程調度策略structsched_param     schedparam;      //線程的調度優先級int                   inheritsched;    //線程的繼承性int                   scope;           //線程的作用域size_t                guardsize;       //線程棧末尾的警戒緩沖區大小int                   stackaddr_set;   //線程的棧設置void*                 stackaddr;       //線程棧的位置size_t                stacksize;       //線程棧的大小
}pthread_attr_t;

屬性值不能直接設置,須使用相關函數進行操作,初始化的函數為pthread_attr_init,這個函數必須在pthread_create函數之前調用。之后須用pthread_attr_destroy函數來釋放資源。線程屬性主要包括如下屬性:作用域(scope)、棧尺寸(stack size)、棧地址(stack address)、優先級(priority)、分離的狀態(detached state)、調度策略和參數(scheduling policy and parameters)。默認的屬性為非綁定、非分離、缺省1M的堆棧、與父進程同樣級別的優先級。

線程的分離

分離狀態屬性確定使用線程屬性對象 attr 創建的線程是在可連接狀態還是可分離狀態下創建。

如果在創建線程時就知道不需要了解線程的終止狀態,就可以修改pthread_attr_t結構中的detachstate線程屬性,讓線程一開始就處于分離狀態。可以使用pthread_attr_setdetachstate函數把線程屬性detachstate設置成以下兩個合法值之一:

PTHREAD_CREATE_DETACHED
PTHREAD_CREATE_JOINABLE
		/* 設置線程的分離狀態 */int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);/* 獲取線程的分離狀態 */	int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);

注意事項:如果設置一個線程為分離線程,而這個線程運行又非常快,它很可能在pthread_create函數返回之前就終止了,

它終止以后就可能將線程號和系統資源移交給其他的線程使用,這樣調用pthread_create的線程就得到了錯誤的線程號。

解決方法:要避免這種情況可以采取一定的同步措施,最簡單的方法之一是可以在被創建的線程里調用pthread_cond_timedwait函數,讓這個線程等待一會兒,留出足夠的時間讓函數pthread_create返回。設置一段等待時間,是在多線程編程里常用的方法。

線程的棧地址

POSIX.1定義了兩個常量_POSIX_THREAD_ATTR_STACKADDR 和_POSIX_THREAD_ATTR_STACKSIZE檢測系統是否支持棧屬性。也可以給sysconf函數傳遞_SC_THREAD_ATTR_STACKADDR或 _SC_THREAD_ATTR_STACKSIZE來進行檢測。

當進程棧地址空間不夠用時,指定新建線程使用由malloc分配的空間作為自己的棧空間。通過pthread_attr_setstack和pthread_attr_getstack兩個函數分別設置和獲取線程的棧地址。

int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr, size_t stacksize);int pthread_attr_getstack(const pthread_attr_t *attr,void **stackaddr, size_t *stacksize);

線程棧大小

當系統中有很多線程時,可能需要減小每個線程棧的默認大小,防止進程的地址空間不夠用。當線程調用的函數會分配很大的局部變量或者函數調用層次很深時,可能需要增大線程棧的默認大小。

函數pthread_attr_getstacksize和 pthread_attr_setstacksize可以設置或者獲取線程的棧大小。

       int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);

線程的調度策略

POSIX標準指定了三種調度策略:先入先出策略 (SCHED_FIFO)、循環策略 (SCHED_RR) 和自定義策略 (SCHED_OTHER)。SCHED_FIFO 是基于隊列的調度程序,對于每個優先級都會使用不同的隊列。SCHED_RR 與 FIFO 相似,不同的是前者的每個線程都有一個執行時間配額。SCHED_FIFO 和 SCHED_RR 是對 POSIX Realtime 的擴展。SCHED_OTHER 是缺省的調度策略。

  1. 新線程默認使用 SCHED_OTHER 調度策略。線程一旦開始運行,直到被搶占或者直到線程阻塞或停止為止。
  2. SCHED_FIFO
    如果調用進程具有有效的用戶 ID ,則爭用范圍為系統 (PTHREAD_SCOPE_SYSTEM) 的先入先出線程屬于實時 (RT) 調度類。如果這些線程未被優先級更高的線程搶占,則會繼續處理該線程,直到該線程放棄或阻塞為止。對于具有進程爭用范圍 (PTHREAD_SCOPE_PROCESS)) 的線程或其調用進程沒有有效用戶 ID 的線程,請使用 SCHED_FIFO,SCHED_FIFO 基于 TS 調度類。
  3. SCHED_RR
    如果調用進程具有有效的用戶 ID ,則爭用范圍為系統 (PTHREAD_SCOPE_SYSTEM)) 的循環線程屬于實時 (RT) 調度類。如果這些線程未被優先級更高的線程搶占,并且這些線程沒有放棄或阻塞,則在系統確定的時間段內將一直執行這些線程。對于具有進程爭用范圍 (PTHREAD_SCOPE_PROCESS) 的線程,請使用 SCHED_RR(基于 TS 調度類)。此外,這些線程的調用進程沒有有效的用戶 ID 。
      int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);

參數policy可以為SCHED_FIFO, SCHED_RR, and SCHED_OTHER

線程優先級

線程優先級存放在結構sched_param中,

struct sched_param {int sched_priority;     /* Scheduling priority */};

可以通過pthread_attr_setschedparam()和pthread_attr_getschedparam設置和獲取線程的調度優先級 ,它的完整定義是:

       int pthread_attr_setschedparam(pthread_attr_t *attr,const struct sched_param *param);int pthread_attr_getschedparam(const pthread_attr_t *attr,struct sched_param *param);

3 線程的同步

參考文章

https://blog.csdn.net/qq_43412060/article/details/106989170
https://www.cnblogs.com/wsw-seu/p/8036218.html

互斥鎖

互斥鎖用pthread_mutex_t數據類型表示,互斥鎖可以用來控制線程對共享資源的互斥訪問,確保同一時間只有一個線程訪問數據 。

/* 初始化互斥鎖 */
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
/* 銷毀互斥鎖 */
int pthread_mutex_destroy(pthread_mutex_t *mutex);
/* 對互斥鎖加鎖 */
int pthread_mutex_lock(pthread_mutex_t *mutex);
/* 對互斥鎖嘗試加鎖 */
int pthread_mutex_trylock(pthread_mutex_t *mutex);
/* 對互斥鎖解鎖 */
int pthread_mutex_unlock(pthread_mutex_t *mutex);

接下來我們來實現主線程負責接收用戶輸入,函數線程負責將用戶輸入打印到終端界面

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>#include<pthread.h>
#include<time.h>
#include<fcntl.h>pthread_mutex_t mutex;char buff[128] = {0};void *fun(void *arg)
{while(1){pthread_mutex_lock(&mutex);if(strncmp(buff,"end",3) == 0){break;}printf("fun :%s\n",buff);memset(buff,0,128);int n = rand() % 3 +1;sleep(n);pthread_mutex_unlock(&mutex);n = rand() % 3 + 1;sleep(n);}
}int main()
{srand((unsigned int)(time(NULL) * time(NULL)));pthread_mutex_init(&mutex,NULL);//初始化的鎖是解鎖狀態的//創建一個線程pthread_t id;int res = pthread_create(&id,NULL,fun,NULL);assert(res == 0);while(1){pthread_mutex_lock(&mutex);printf("input:");fgets(buff,127,stdin);pthread_mutex_unlock(&mutex);if(strncmp(buff,"end",3) == 0){break;}int n = rand()%3 + 1;sleep(n);}//等待函數線程的結束pthread_join(id,NULL);pthread_mutex_destroy(&mutex);exit(0);
}

在這里插入圖片描述

讀寫鎖

讀寫鎖是更高級的互斥鎖,有更高的并行性。互斥鎖只允許一個線程對臨界區訪問,而讀寫鎖可以讓多個讀者并發訪問。
讀寫鎖可以多個讀者讀,但只允許一個寫者寫。

  1. 如果一個線程用讀鎖鎖定了臨界區,那么其他線程也可以用讀鎖來進入臨界區,這樣就可以多個線程并行操作。但這個時候,如果再進行寫鎖加鎖就會發生阻塞,寫鎖請求阻塞后,后面如果繼續有讀鎖來請求,這些后來的讀鎖都會被阻塞!這樣避免了讀鎖長期占用資源,防止寫鎖饑餓!
  2. 如果一個線程用寫鎖鎖住了臨界區,那么其他線程不管是讀鎖還是寫鎖都會發生阻塞!
/* 讀寫鎖的銷毀 */
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
/* 讀寫鎖的初始化 */
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;/* 讀寫鎖加鎖解鎖 */
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

我們使用讀寫鎖來實現兩個線程讀寫一段數據
主線程寫入時加寫鎖,兩個函數線程讀取時加讀鎖,這樣兩個函數線程可以同時讀取,

# include<unistd.h>
#include <stdlib.h>
# include<stdio.h>
# include<string.h>
# include<time.h>
# include<assert.h>
# include<pthread.h>pthread_rwlock_t rwlock;//創建讀寫鎖
char buff[128]={0};void* fun(void* arg)//讀數據
{while(1){pthread_rwlock_rdlock(&rwlock);if(strncmp(buff,"end",3)==0){break;}printf("fun:%s\n",buff);//memset(buff,0,128);int n=rand()%3+1;sleep(n);pthread_rwlock_unlock(&rwlock);n=rand()%3+1;sleep(1);}
}
void* fun1(void* arg)//讀數據
{while(1){pthread_rwlock_rdlock(&rwlock);if(strncmp(buff,"end",3)==0){break;}printf("fun1:%s\n",buff);//memset(buff,0,128);int n=rand()%3+1;sleep(n);pthread_rwlock_unlock(&rwlock);n=rand()%3+1;sleep(1);}
}
int main()
{srand((unsigned int)(time(NULL)*time(NULL)));pthread_rwlock_init(&rwlock,NULL);//初始化pthread_t id[2];int res=pthread_create(&id[0],NULL,fun,NULL);//創建線程int r=pthread_create(&id[1],NULL,fun1,NULL);assert(res==0);while(1)//寫數據{pthread_rwlock_wrlock(&rwlock);printf("input:");fgets(buff,127,stdin);pthread_rwlock_unlock(&rwlock);if(strncmp(buff,"end",3)==0){break;}int n=rand()%3+1;sleep(1);}pthread_join(id[0],NULL);pthread_join(id[1],NULL);pthread_rwlock_destroy(&rwlock);
}

在這里插入圖片描述

條件變量

條件變量是利用線程間共享全局變量進行同步的一種機制。一個線程修改條件,另一個線程等待條件,一旦等到自己需要的條件,就去運行。條件變量用pthread_cond_t類型的實例表示。

信號量

這個信號量和進程間用的信號量作用類似,當線程訪問一些有限的公共資源時,就必須做到線程間同步訪問。其實就類似于一個計數器,有一個初始值用于記錄臨界資源的個數。信號量由sem_t的實例表示。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379557.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379557.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379557.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

博客上一些項目相關源碼鏈接

GitHub&#xff1a;https://github.com/beyondyanyu/Sayingyy

重新開啟Ctrl+Alt+Backspace快捷鍵

UBUNTU老用戶知道CtrlAltBackspace這個快捷鍵是用來快速重啟X的在9.04中被默認關閉了&#xff0c;那如何來打開它呢&#xff1f;在終端中輸入&#xff1a;sudo gedit /etc/X11/xorg.conf在其中加入&#xff1a;Section “ServerFlags”Option “DontZap” “false”EndSection退…

Java LocalDate類| 帶示例的getDayOfYear()方法

LocalDate類的getDayOfYear()方法 (LocalDate Class getDayOfYear() method) getDayOfYear() method is available in java.time package. getDayOfYear()方法在java.time包中可用。 getDayOfYear() method is used to get the day-of-year field value of this LocalDate obje…

火腿三明治定理

定理&#xff1a;任意給定一個火腿三明治&#xff0c;總有一刀能把它切開&#xff0c;使得火腿、奶酪和面包片恰好都被分成兩等份。 而且更有趣的是&#xff0c;這個定理的名字真的就叫做“火腿三明治定理”&#xff08;ham sandwich theorem&#xff09;。它是由數學家亞瑟?斯…

如何給Linux操作系統(CentOS 7為例)云服務器配置環境等一系列東西

1.首先&#xff0c;你得去購買一個云服務器&#xff08;這里以阿里云學生服務器為例&#xff0c;學生必須實名認證&#xff09; 打開阿里云&#xff0c;搜索學生服務器點擊進入即可 公網ip為連接云服務器的主機 自定義密碼為連接云服務器是需要輸入的密碼 購買即可 點擊云服…

Linux系統編程---I/O多路復用

文章目錄1 什么是IO多路復用2 解決什么問題說在前面I/O模型阻塞I/O非阻塞I/OIO多路復用信號驅動IO異步IO3 目前有哪些IO多路復用的方案解決方案總覽常見軟件的IO多路復用方案4 具體怎么用selectpollepolllevel-triggered and edge-triggered狀態變化通知(edge-triggered)模式下…

[轉帖]純屬娛樂——變形金剛vs天網

[轉帖]變形金剛2的影評-《變形金剛3 天網反擊戰》有一個問題困擾了我足足二十年&#xff1a;為什么汽車人要幫地球人&#xff1f;光用“所有有感知的生物都應享有自由”這個法則是根本說不過去的&#xff0c;因為豬也有感知&#xff0c;但人類就把豬圈養起來&#xff0c;隨意殺…

c#中textbox屬性_C#.Net中的TextBox.MaxLength屬性與示例

c#中textbox屬性Here we are demonstrating use of MaxLength property of TextBox. 在這里&#xff0c;我們演示了TextBox的MaxLength屬性的使用。 MaxLength property of TextBox is used to set maximum number of character that we can input into a TextBox. Limit of M…

IIS7 MVC網站生成、發布

(1)生成。 確保System.Web.Mvc.dll在bin目錄下 (2)發布網站到文件系統 (3)在IIS中為網站添加應用程序池&#xff08;一個虛擬目錄&#xff0c;一個應用程序池&#xff09; (4)添加在默認網站下添加虛擬目錄 &#xff08;5&#xff09;轉換為應用程序 至此&#xff0c;部署完畢 …

標題:明碼

轉載&#xff1a;https://blog.csdn.net/u011747888/article/details/79781040 標題&#xff1a;明碼 漢字的字形存在于字庫中&#xff0c;即便在今天&#xff0c;16點陣的字庫也仍然使用廣泛。 16點陣的字庫把每個漢字看成是16x16個像素信息。并把這些信息記錄在字節中。 一…

C語言多維數組

文章目錄多維數組數組名下標指向數組的指針作為函數參數的多維數組指針數組小結多維數組 如果某個數組的維數超過1&#xff0c;它就被稱為多維數組&#xff0c;例如&#xff0c;下面這個聲明&#xff1a; int matrix[6][10]創建了一個包含60個元素的矩陣。但是&#xff0c;它…

ubuntu路由器聯網_路由器及其協議簡介| 聯網

ubuntu路由器聯網路由器簡介 (Introduction to Router) Routers are network layer devices. Data on the network layer is known as packets. Routers work to forward packets from one network to another. Routers also maintain the address table. 路由器是網絡層設備。…

XPath學習:軸(5)——descendant-or-self

XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進行遍歷。 XPath 是 W3C XSLT 標準的主要元素&#xff0c;并且 XQuery 和 XPointer 同時被構建于 XPath 表達之上。 推薦一個挺不錯的網站&#xff1a;http://www.zvon.org/xxl/XPathTutorial…

linux設備驅動開發---平臺設備驅動程序

文章目錄1 平臺驅動程序2 平臺設備2.1 資源和平臺數據1 設備配置---廢棄的舊方法資源平臺數據聲明平臺設備2 設備配置---推薦的新方法3 設備、驅動程序和總線匹配OF風格ACPIID表匹配匹配平臺設備的名字和平臺驅動的名字平臺設備和平臺驅動程序如何匹配4 Platfrom架構驅動程序有…

標題:乘積尾零

標題&#xff1a;乘積尾零 如下的10行數據&#xff0c;每行有10個整數&#xff0c;請你求出它們的乘積的末尾有多少個零&#xff1f; 5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 9937 1173 6866 3397 4759 7557 3070…

Robots.txt指南

Robots.txt指南當搜索引擎訪問一個網站時&#xff0c;它首先會檢查該網站的根域下是否有一個叫做robots.txt的純文本文件。Robots.txt文件用于限定搜索引擎對其 網站的訪問范圍&#xff0c;即告訴搜索引擎網站中哪些文件是允許它進行檢索(下載)的。這就是大家在網絡上常看到的“…

fwrite函數的用法示例_C語言中的fwrite()函數(帶有示例)

fwrite函數的用法示例C中的fwrite()函數 (fwrite() function in C) Prototype: 原型&#xff1a; size_t fwrite(void *buffer, size_t length, size_t count, FILE *filename);Parameters: 參數&#xff1a; void *buffer, size_t length, size_t count, FILE *filenameRetu…

標題:遞增三元組

標題&#xff1a;遞增三元組 給定三個整數數組 A [A1, A2, … AN], B [B1, B2, … BN], C [C1, C2, … CN]&#xff0c; 請你統計有多少個三元組(i, j, k) 滿足&#xff1a; 1 < i, j, k < NAi < Bj < Ck 【輸入格式】 第一行包含一個整數N。 第二行包含N個整…

伙伴算法、slab機制、內存管理函數

文章目錄1 伙伴算法頁框操作alloc_pages()2 slabslab機制要解決的問題使用高速緩存3 內存管理函數kmallockzallocvmallocvzalloc區別參考文章內核使用struct page結構體描述每個物理頁&#xff0c;也叫頁框。內核在很多情況下&#xff0c;需要申請連續的頁框&#xff0c;而且數…

eval 函數 代替函數_eval()函數以及JavaScript中的示例

eval 函數 代替函數eval()函數 (eval() function) eval() function is a predefined global function in JavaScript and it is used to evaluate (execute) an expression, which is passed to the function as a parameter. It can also evaluate any JavaScript code. eval(…