1、信號來自進程或內核
2、線程共享進程的代碼空間和數據空間(全局變量或靜態變量),文件描述符,信號,以及malloc分配的內存,每個線程擁有獨立的棧空間和程序計數器,在創建線程時,調用pthread_create函數的線程和新建線程的執行順序隨機
3、在linux中,使用輕量級進程來模擬線程,線程操作的相關函數通過第三方線程庫 (Linuxthreads 或 Native POSIX Thread Library(NPTL))來實現
4、down()/down_interruptible()用於內核空間執行單元的同步,其中down(struct semaphore *sem)用於獲取信號量sem,如果調用者獲取不到信號量,將會導致睡眠,進入睡眠狀態的進程不能被信號打斷,而因down_interruptible進入睡眠狀態的進程能被信號打斷,導致該函數返回。
5、時間片:進程處於運行狀態時所剩余的時鍾滴答數 ,每次時鍾中斷到來時,這個 值就減1。當這個域的值變得越來越小,直至為0 時,就把need_resched 域置1(在調度時機到來時,檢測這個域的值,如果為1,則調用schedule())
6、OS時鍾(嘀嗒時鍾)作為linux系統調度的基准時鍾。
7、linux多線程編程中,可使用sleep函數來釋放線程的cpu控制權,測試代碼如下
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
void *SleepTest1(void *arg)
{
while(1)
{
printf("the sleeptest1 is ok!\n");
sleep(3);
}
}
void *SleepTest2(void *arg)
{
while(1)
{
printf("the sleeptest2 is ok!\n");
sleep(10);
}
}
int main(int argc, char *argv[])
{
pthread_t tid[2];
int ret;
ret = pthread_create(&tid[0], NULL, SleepTest1, NULL);
if(ret < 0)
{
printf("pthread_create");
return -1;
}
ret = pthread_create(&tid[1], NULL, SleepTest2, NULL);
if(ret < 0)
{
perror("pthread_create");
return -1;
}
printf("the thread1 and thread2 create ok!\n");
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
printf("the thread exit!\n");
return 0;
}
8、僵死進程:在每個進程退出的時候,內核釋放該進程所有的資源(包括打開的文件、占用的內存等),但是仍然為其保留一定的信息(包括進程號,退出狀態,運行時間等),直到父進程通過外wait/waitpid來取時才釋放。此時該進程處於僵死狀態。
9、進程退出
進程在退出時,必須釋放它所擁有的資源,並通過某種方式(發送SIGCHLD信號)告訴父進程。進程的退出一般是顯示或隱式地調用了eixt(),或者接受了某種信號。不過什么原因退出,最終都調用了do_exit。
用於進程退出的系統調用有兩個exit和exit_group,exit只是終止某個進程,而exit_group整個線程中的進程。它們在內核中的服務函數分別為sys_exit和sys_exit_group,它們又分別調用了do_exit和do_group_exit。而do_group最終又調用了do_exit(do_exit定義在kernel/exit.c中)。
10、查看某進程打開的文件描述符
[root@localhost proc]# cd 1328/
[root@localhost 1328]# ls
attr clear_refs cpuset exe io loginuid mountinfo net pagemap sched smaps statm task
auxv cmdline cwd fd latency maps mounts oom_adj personality schedstat stack status wchan
cgroup coredump_filter environ fdinfo limits mem mountstats oom_score root sessionid stat syscall
[root@localhost 1328]# cd fdinfo/
[root@localhost fdinfo]# ls
0 1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 3 4 5 6 7 8 9
[root@localhost fdinfo]#
fdinfo文件夾中列出的數字,即該進程打開的文件描述符
11、fork函數
fork在復制的時候,parent順序執行過的代碼在chiled中應該是不會再執行!
12、進程上下文和中斷上下文詳解
用戶空間的應用程序,通過系統調用,進入內核空間。這個時候用戶空間的進程要傳遞 很多變量、參數的值給內核,內核態運行的時候也要保存用戶進程的一些寄存 器值、變量等。所謂的“進程上下文”,可以看作是用戶進程傳遞給內核的這些參數以及內核要保存的那一整套的變量和寄存器值和當時的環境等。
硬件通過觸發信號,導致內核調用中斷處理程序,進入內核空間。這個過程中,硬件的 一些變量和參數也要傳遞給內核,內核通過這些參數進行中斷處理。所謂的“ 中斷上下文”,其實也可以看作就是硬件傳遞過來的這些參數和內核需要保存的一些其他環境(主要是當前被打斷執行的進程環境)。
LINUX完全注釋中的一段話:
當一個進程在執行時,CPU的所有寄存器中的值、進程的狀態以及堆棧中的內容被稱 為該進程的上下文。當內核需要切換到另一個進程時,它需要保存當前進程的 所有狀態,即保存當前進程的上下文,以便在再次執行該進程時,能夠必得到切換時的狀態執行下去。在LINUX中,當前進程上下文均保存在進程的任務數據結 構中。在發生中斷時,內核就在被中斷進程的上下文中,在內核態下執行中斷服務例程。但同時會保留所有需要用到的資源,以便中繼服務結束時能恢復被中斷進程 的執行。
進程上下文是一種內核所處的操作模式,此時內核代表進程執行--例如執行系統調用或運行內核線程。
上下文context: 上下文簡單說來就是一個環境,相對於進程而言,就是進程執行時的環境。具體來說就是各個變量和數據,包括所有的寄存器變量、進程打開的文件、內存信息等。
一個進程的上下文可以分為三個部分:用戶級上下文、寄存器上下文以及系統級上下文。
用戶級上下文: 正文、數據、用戶堆棧以及共享存儲區;
寄存器上下文: 通用寄存器、程序寄存器(IP)、處理器狀態寄存器(EFLAGS)、棧指針(ESP);
系統級上下文: 進程控制塊task_struct、內存管理信息(mm_struct、vm_area_struct、pgd、pte)、內核棧。
當發生進程調度時,進行進程切換就是上下文切換(context switch).操作系統必須對上面提到的全部信息進行切換,新調度的進程才能運行。而系統調用進行的模式切換(mode switch)。模式切換與進程切換比較起來,容易很多,而且節省時間,因為模式切換最主要的任務只是切換進程寄存器上下文的切換。
13、進程終止方式
在Linux中進程退出分為了正常退出和異常退出兩種。
1>正常退出
a. 在main()函數中執行return 。
b.調用exit()函數
c.調用_exit()函數
2>異常退出
a.調用abort函數
b.進程收到某個信號,而該信號使程序終止。
不管 是那種退出方式,系統最終都會執行內核中的同一代碼。這段代碼用來關閉進程所用已打開的文件描述符,釋放它所占用的內存和其他資源。
3>_exit()和 exit()區別:
a._exit()執行后立即返回給內核,而exit()要先執行一些清除操作,然后將控制權交給內核。
b. exit() 和 _exit()區別之一: 前者支持調用用戶自定義的清除程序(atexit函數注冊)
c. 調用_exit函數時,其會關閉進程所有的文件描述符,清理內存以及其他一些內核清理函數,但不會刷
新流(stdin, stdout, stderr ...). exit函數是在_exit函數之上的一個封裝,其會調用_exit,並在
調用之前先刷新流。
14、copy-on-write技術
fork會將調用進程的所有內容原封不動的拷貝到新產生的子進程中去,這些拷貝的動作很消耗時間,而如果fork完之后我們馬上就調用exec,這些辛辛苦苦拷貝來的東西又會被立刻抹掉,這看起來非常不划算,於是人們設計了一種"寫時拷貝(copy-on-write)"技術,使得fork結束后並不立刻復制父進程的內容,而是到了真正使用的時候才復制,這樣如果下一條語句是exec,它就不會白白作無用功了,也就提高了效率。
15、后台程序運行需注意幾點:
在后台運行作業時要當心:需要用戶交互的命令不要放在后台執行,因為這樣你的機器就會在那里傻等。不過,作業在后台運行一樣會將結果輸出到屏幕上,干擾你的工作。如果放在后台運行的作業會產生大量的輸出,最好使用下面的方法把它的輸出重定向到某個文件中:
command >out.file 2>&1 &
16、fflush函數
標准C的fflush()支持刷新輸出緩沖區,對於輸入緩沖區無定義