Linux程序執行緒實驗
實驗1 程序
1.目的
通過觀察、分析實驗現象,深入理解程序及程序在排程執行和記憶體空間等方面的特點,掌握在POSIX 規範中fork和kill系統呼叫的功能和使用。
實驗前準備
學習man 命令的用法,通過它檢視fork 和kill 系統呼叫的線上幫助,並閱讀參考資料,學會fork 與kill 的用法。複習C 語言的相關內容。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
/* 允許建立的子程序個數最大值 */
#define MAX_CHILD_NUMBER 10
/* 子程序睡眠時間 */
#define SLEEP_INTERVAL 2
int proc_number=0;
/* 子程序的自編號,從0開始 */
void do_something();
int main(int argc, char* argv[])
{
/* 子程序個數 */
int child_proc_number = MAX_CHILD_NUMBER;
int i,ch;
pid_t child_pid;
pid_t pid[10 ]={0}; /* 存放每個子程序的id */
if (argc > 1) /* 命令列引數第一個引數表示子程序個數*/
{
child_proc_number = atoi(argv[1]);
child_proc_number= (child_proc_number > 10) ? 10 : child_proc_number;
}
for (i=0; i<child_proc_number; i++)
{
child_pid=fork();
if(child_pid!=0 )
{
pid[i]=child_pid;
}
else
{
/* 填寫程式碼,建立child_proc_number個子程序要執行
* proc_number = i;
* do_something();
* 父程序把子程序的id儲存到pid[i]
* */
proc_number=i;
do_something();
}
}
/* 讓使用者選擇殺死程序,數字表示殺死該程序,q退出 */
while ((ch = getchar()) != 'q')
{
if (isdigit(ch))
{
/* 填寫程式碼,向pid[ch-'0']發訊號SIGTERM,*殺死該子程序 */
kill(pid[ch-'0'],SIGTERM);
}
}
/* 在這裡填寫程式碼,殺死本組的所有程序 */
kill(0,SIGTERM);
return 0;
}
void do_something()
{
for(;;)
{
printf("This is process No.%d and its pid is %d\n", proc_number, getpid());
sleep(SLEEP_INTERVAL); /* 主動阻塞兩秒鐘 */
}
}
執行情況:
[email protected]:~/文件/os$ ./process 3
This is process No.2 and its pid is 3540
This is process No.1 and its pid is 3539
This is process No.0 and its pid is 3538
This is process No.1 and its pid is 3539
This is process No.0 and its pid is 3538
This is process No.2 and its pid is 3540
1
This is process No.0 and its pid is 3538
This is process No.2 and its pid is 3540
2
This is process No.0 and its pid is 3538
3
已終止
kill()函式用於刪除執行中的程式或者任務。呼叫格式為:
kill(int PID, int IID);
其中:PID是要被殺死的程序號,IID為向將被殺死的程序傳送的中斷號.
實驗3 執行緒
目的
通過觀察、分析實驗現象,深入理解執行緒及執行緒在排程執行和記憶體空間等方面的特點,並掌握執行緒與程序的區別。掌握POSIX 規範中pthread_create() 函式的功能和使用方法。
實驗前準備
閱讀參考資料,瞭解執行緒的建立等相關係統呼叫。
/* POSIX 下執行緒控制的實驗程式殘缺版 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <pthread.h>
#define MAX_THREAD 3 /* 執行緒的個數 */
unsigned long long main_counter, counter[MAX_THREAD];
/* unsigned long long是比long還長的整數 */
void* thread_worker(void*);
int main(int argc, char* argv[])
{
int i, rtn, ch;
pthread_t pthread_id[MAX_THREAD] = {0}; /* 存放執行緒id*/
for (i=0; i<MAX_THREAD; i++)
{
/* 在這裡填寫程式碼,用pthread_create建一個普通的執行緒,執行緒id存入pthread_id[i],執行緒執行函式是thread_worker並i作為引數傳遞給執行緒 */
rtn=pthread_create(& pthread_id[i],NULL,(void *)thread_worker,i);
}
do
{
/* 使用者按一次回車執行下面的迴圈體一次。按q退出 */
unsigned long long sum = 0;
/* 求所有執行緒的counter的和 */
for (i=0; i<MAX_THREAD; i++)
{
/* 求所有counter的和 */
sum += counter[i];
printf("%llu ", counter[i]);
}
printf("%llu/%llu", main_counter, sum);
} while ((ch = getchar()) != 'q');
return 0;
}
void* thread_worker(void* p)
{
int thread_num;
/* 在這裡填寫程式碼,把main中的i的值傳遞給thread_num */
thread_num=p;
for(;;)
{
/* 無限迴圈 */
counter[thread_num]++; /* 本執行緒的counter加一*/
main_counter++; /* 主counter 加一 */
}
}
執行情況
zach@zach-i16:~/文件/os$ ./process3
0 3439 0 3781/3439
147825977 173501711 76050439 278869308/397378126
425287134 219440108 121358850 536654323/766086076
640152823 368891179 198391806 847618905/1207435792
738229522 599211834 248175335 1113963652/1585616684
968491690 636516600 286022645 1327432250/1891030934q
可以從執行情況看出main_counter(總的迴圈次數)和sum(3個執行緒各自迴圈次數的總和)值不相等,但理論上兩個數的值應該是相等的.
因為假設main_counter=0時,當執行緒1還沒有完成加1操作的時候,main_counter還是為0此時執行緒2也開始執行main_counter++,兩執行緒各執行一次加1操作,執行緒1將main_counter值變為1,執行緒2也將main_的值變為1,導致main_counter實際只加了1,比理論值偏小.
為了解決這一問題,給輸出的時候加鎖:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <pthread.h>
#define MAX_THREAD 3 /* 執行緒的個數 */
unsigned long long main_counter, counter[MAX_THREAD];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/* unsigned long long是比long還長的整數 */
void* thread_worker(void*);
int main(int argc, char* argv[])
{ int i, rtn, ch;
pthread_t pthread_id[MAX_THREAD] = {0}; /* 存放執行緒id*/
for (i=0; i<MAX_THREAD; i++)
{
rtn=pthread_create(&pthread_id[i],NULL,(void *)thread_worker,i);
}
do {
pthread_mutex_lock(&mutex);
unsigned long long sum = 0;
for (i=0; i<MAX_THREAD; i++)
{
sum += counter[i];
printf("%llu ", counter[i]);
}
printf("%llu/%llu", main_counter, sum);
pthread_mutex_unlock(&mutex);
} while ((ch = getchar()) != 'q');
pthread_mutex_destroy(&mutex);
return 0;
}
void* thread_worker(void* p)
{
int thread_num;
thread_num=p;
/* 在這裡填寫程式碼,把main中的i的值傳遞給thread_num */
for(;;)
{ /* 無限迴圈 */
pthread_mutex_lock(&mutex);
counter[thread_num]++; /* 本執行緒的counter加一 */
main_counter++; /* 主counter 加一 */
pthread_mutex_unlock(&mutex);
}
}
執行情況:
zach@zach-i16:~/文件/os$ ./process3
466 0 0 466/466
2470436 2513089 2641403 7624928/7624928
4676030 5015065 5015462 14706557/14706557
7866636 8291442 8161852 24319930/24319930
12619489 12585861 12681943 37887293/37887293
13956112 13899913 14071728 41927753/41927753
16308110 15997805 16218050 48523965/48523965
16980084 16692473 16886541 50559098/50559098q
注意因為pthread庫不是Linux系統預設的庫,所以編譯時應該連線庫函式
gcc process3.c -l pthread -o process3
實驗4 互斥
目的
通過觀察、分析實驗現象,深入理解理解互斥鎖的原理及特點掌握在POSIX 規範中的互斥函式的功能及使用方法。
實驗前準備
準備好上節實驗完成的程式thread.c 。
閱讀參考資料,瞭解互斥鎖的加解鎖機制及相關的系統呼叫。
實驗內容
//* POSIX 下執行緒死鎖的演示程式 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <pthread.h>
#define LOOP_TIMES 10000
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
/*用巨集PTHREAD_MUTEX_INITIALIZER來初始化 */
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
void* thread_worker(void*);
void critical_section(int thread_num, int i);
int main(void)
{
int rtn, i;
pthread_t pthread_id = 0; /* 存放子執行緒的id */
rtn = pthread_create(&pthread_id, NULL, thread_worker, NULL );
if(rtn != 0)
{
printf("pthread_create ERROR!\n");
return -1;
}
for (i=0; i<LOOP_TIMES; i++)
{
pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
critical_section(1, i);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_destroy(&mutex1);
pthread_mutex_destroy(&mutex2);
return 0;
}
void* thread_worker(void* p)
{
int i;
for (i=0; i<LOOP_TIMES; i++)
{
pthread_mutex_lock(&mutex1);//本來是先2後1,這裡鎖的順序變一下,變為先1後2
pthread_mutex_lock(&mutex2);
critical_section(2, i);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
}
void critical_section(int thread_num, int i)
{
printf("Thread%d: %d\n", thread_num, i);
}
相關推薦
Linux程序執行緒實驗
實驗1 程序 1.目的 通過觀察、分析實驗現象,深入理解程序及程序在排程執行和記憶體空間等方面的特點,掌握在POSIX 規範中fork和kill系統呼叫的功能和使用。 實驗前準備 學習man 命令的用法,通過它檢視fork 和kill 系統呼叫的
linux程序-執行緒-協程上下文環境的切換與實現
一:程序-執行緒-協程簡介程序和執行緒的主要區別是:程序獨享地址空間和資源,執行緒則共享地址空間和資源,多執行緒就是多棧。1、程序程序是具有一定獨立功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源分配和排程的一個獨立單位。每個程序都有自己的獨立記憶體空間,不同程
Linux 多執行緒和多程序的區別(小結)
最近學習Linux,看到“hairetz的專欄”的帖子不錯,特轉來大家一起學習。 很想寫點關於多程序和多執行緒的東西,我確實很愛他們。但是每每想動手寫點關於他們的東西,卻總是求全心理作祟,始終動不了手。 今天終於下了決心,寫點東西,以後可以再修修補補也無妨。一.為何需要多程序(或者多執行緒),為何需
Linux 檢視程序以及子程序/執行緒
1、 檢視程序資訊 # ps -ef | grep 114 root 114 2 0 Jun23 ? 00:00:00 [kswapd1] 2、檢視程序的子程序/執行緒 # pstree -p 5346 或者# ps m
Java的快速排序----在程序執行緒模擬實驗中遇到的排序問題
前言:最近作業系統課需要完成PCB程序執行緒模擬實驗,老師給的c語言版實現程式碼,想著用java實現一波,然後在其中遇到了排序問題,我採用快速排序的演算法進行優先度排序。本人程式設計菜鳥一隻,不喜勿噴,另外,程式碼中有大量註釋,請做好心理準備... 快速排序原理:基於分治
Linux多執行緒程式設計時如何檢視一個程序中的某個執行緒是否存活
pthread_kill: 別被名字嚇到,pthread_kill可不是kill,而是向執行緒傳送signal。還記得signal嗎,大部分signal的預設動作是終止程序的執行,所以,我們才要用signal()去抓訊號並加上處理函式。 int pthread_kil
linux核心執行緒 [核心執行緒 使用者程序 使用者執行緒]
只有“核心執行緒”的概念,不存在所謂的“核心程序”。 核心執行緒的作用主要有: 週期性的將dirty記憶體頁同步到磁碟裝置上。 比如 bpflush執行緒週期性的把dirty資料寫回磁碟記憶體頁很少的情況下,把記憶體page 交換到磁碟空間。 比如kswapd,系統會為每
學習筆記之linux多執行緒和多程序優缺點
Linux下的多執行緒 執行緒和程序相比的缺點和優點 優點: 多執行緒對資源的需求少,建立的代價比程序小 缺點:除錯困難,非常容易出錯 執行緒擁有獨立的程式計數器,獨立的棧空間,共享程序的全域性記憶體和堆記憶體,共享檔案描述符,共享虛擬記憶體。繼承訊號的處理可以訪問程序
Linux的程序/執行緒間通訊方式總結
Linux系統中的程序間通訊方式主要以下幾種: 同一主機上的程序通訊方式 * UNIX程序間通訊方式: 包括管道(PIPE), 有名管道(FIFO), 和訊號(Signal) * System V程序通訊方式:包括訊號量(Semaphore), 訊息佇列
Linux — POSIX 執行緒基礎
執行緒對於Linux後臺程式設計師來說並不陌生,執行緒帶給我們併發能力的提升,也提高了軟體開發和問題定位的難度,本文 嘗試結合GlibC 程式碼, 對POSIX的執行緒做一個簡單說明,重點介紹執行緒的建立,釋放和連線上需要注意的問題。 多程序和多執行緒的都只有一個目的,並行處理,提高CP
Linux多執行緒程式設計---執行緒間同步(互斥鎖、條件變數、訊號量和讀寫鎖)
本篇博文轉自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數、訊號量和讀寫鎖。 下面是思維導
LINUX 多執行緒 JNI 回撥 java static
1.Linux 開啟執行緒 //渲染執行緒Rendering void* thread_rendering_process(void *lParam) { unsigned int local_wr; int index; &
程序/執行緒同步的方式和機制,程序間通訊【轉】
(轉自:https://www.cnblogs.com/virusolf/p/5331946.html) 一、程序/執行緒間同步機制。 臨界區、互斥區、事件、訊號量四種方式臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)的區別
linux 多執行緒之訊號量 sem_init
1. 什麼是訊號量 linux sem 訊號量是一種特殊的變數,訪問具有原子性, 用於解決程序或執行緒間共享資源引發的同步問題。 使用者態程序對 sem 訊號量可以有以下兩種操作: 等待訊號量 當訊號量值為 0 時,程式等待;當訊號量值大於 0 時,訊號量減 1,程式
程序執行緒間的同步機制
因為是轉載文章, 在此標明出處,如有冒犯請聯絡本人。 因為好的文章,以前只想收藏,但連線有時候會失效,所以現在碰到好的直接轉到自己這裡。 原文出處:http://www.cnblogs.com/memewry/archive/2012/08/22/2651696.html
Linux多執行緒學習總結
原文:https://www.cnblogs.com/luoxn28/p/6087649.html Linux多執行緒學習總結 執行緒是程式中完成一個獨立任務的完整執行序列,即一個可排程的實體;程序相當於執行中程式的一種抽象。根據執行環境的排程者的身份,執行緒可分為核心執行緒和使用者執行
Python程序,執行緒以及協程對比
執行緒:一份程式碼資源有多個箭頭同時執行 程序:拷貝多份程式碼資源中只存在一個箭頭(執行緒)來執行 協程 : 利用程式的阻塞或者暫停時間完成多工 即:資源分配的程式碼是程序,而執行程式碼的是執行緒, 可以理解為程序是工廠的一條流水線,其中執行緒就是流水線上的工人。 協程利用閒散時間加班的有志
Linux多執行緒/多客戶程式設計參考/程式碼
Linux多執行緒/多客戶程式設計參考/程式碼 (1)linux多執行緒程式設計例項及講解 https://blog.csdn.net/m0_37051593/article/details/80719469 (2)Linux多執行緒程式設計——多執行緒與執行緒同步 https://
程序執行緒協程區別
現在多程序多執行緒已經是老生常談了,協程也在最近幾年流行起來。python中有協程庫gevent,py web框架tornado中也用了gevent封裝好的協程。本文主要介紹程序、執行緒和協程三者之間的區別。 一、概念 1、程序 程序是具有一定獨立功能的程式關於某個資料集合上的一次執
Linux中執行緒使用詳解
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!