linux c 多线程 popen(linux c 多线程)
c語言有沒有多線程這個(gè)概念?
線程:線程是程序中的一個(gè)執(zhí)行流,每個(gè)線程都有自己的專有寄存器(棧指針、程序計(jì)數(shù)器等),但代碼區(qū)是共享的,即不同的線程可以執(zhí)行同樣的函數(shù)。
多線程:多線程是指程序中包含多個(gè)執(zhí)行流,即在一個(gè)程序中可以同時(shí)運(yùn)行多個(gè)不同的線程來執(zhí)行不同的任務(wù),也就是說允許單個(gè)程序創(chuàng)建多個(gè)并行執(zhí)行的線程來完成各自的任務(wù)。
C語言的開始設(shè)計(jì),并未設(shè)計(jì)多線程的機(jī)制,由于隨著軟硬件的發(fā)展及需求的發(fā)展。后來C語言才開發(fā)了線程庫以支持多線程的操作、應(yīng)用。
主要基于Linux介紹C多線程。在編譯C的多線程時(shí)候,一方面必須指定Linux C語言線程庫多線程庫pthread,才可以正確編譯(例如:gcc test.c -o test -lpthread);另一方面要包含有關(guān)線程頭文件#include
linux怎么指定線程庫?
大概的介紹一下Linux 的指定CPU運(yùn)行,包括進(jìn)程和線程。linux下的top命令是可以查看當(dāng)前的cpu的運(yùn)行狀態(tài),按1可以查看系統(tǒng)有多少個(gè)CPU,以及每個(gè)CPU的運(yùn)行狀態(tài)。 可是如何查看線程的CPU呢?
top -Hp pid,pid就是你當(dāng)前程序的進(jìn)程號,如果是多線程的話,是可以查看進(jìn)程內(nèi)所有線程的CPU和內(nèi)存使用情況。
pstree可以查看主次線程,同樣的pstree -p pid。可以查看進(jìn)程的線程情況。
taskset這個(gè)其實(shí)才是重點(diǎn),可以查看以及設(shè)置當(dāng)前進(jìn)程或線程運(yùn)行的CPU(設(shè)置親和力)。
taskset -pc pid,查看當(dāng)前進(jìn)程的cpu,當(dāng)然有的時(shí)候不只是一個(gè),taskset -pc cpu_num pid ,cpu_num就是設(shè)置的cpu。 這樣的話基本的命令和操作其實(shí)大家都知道了,接下來就是在代碼中完成這些操作,并通過命令去驗(yàn)證代碼的成功率。 進(jìn)程制定CPU運(yùn)行:
view plain copy #include #include #include #include #include #define __USE_GNU #include #include #include int main(int argc, char* argv) { //sysconf獲取有幾個(gè)CPU int num = sysconf(_SC_NPROCESSORS_CONF); int created_thread = 0; int myid; int i; int j = 0; //原理其實(shí)很簡單,就是通過cpu_set_t進(jìn)行位與操作 cpu_set_t mask; cpu_set_t get; if (argc != 2) { printf("usage : ./cpu numn"); exit(1); } myid = atoi(argv)
; printf("system has %i processor(s). n", num)
; //先進(jìn)行清空,然后設(shè)置掩碼 CPU_ZERO(&mask); CPU_SET(myid, &mask)
; //設(shè)置進(jìn)程的親和力 if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { printf("warning: could not set CPU affinity, continuing...n"); } while (1) { CPU_ZERO(&get); //獲取當(dāng)前進(jìn)程的親和力 if (sched_getaffinity(0, sizeof(get), &get) == -1) { printf("warning: cound not get cpu affinity, continuing...n"); } for (i = 0; i < num; i++) { if (CPU_ISSET(i, &get)) { printf("this process %d is running processor : %dn",getpid(), i); } } } return 0; } 進(jìn)程設(shè)置CPU運(yùn)行,其實(shí)只能是單線程。多線程設(shè)定CPU如下:
view plain copy #define _GNU_SOURCE #include #include #include #include #include #include void *myfun(void *arg) { cpu_set_t mask; cpu_set_t get; char buf; int i; int j; //同樣的先去獲取CPU的個(gè)數(shù) int num = sysconf(_SC_NPROCESSORS_CONF); printf("system has %d processor(s)n", num); for (i = 0; i < num; i++) { CPU_ZERO(&mask); CPU_SET(i, &mask); //這個(gè)其實(shí)和設(shè)置進(jìn)程的親和力基本是一樣的 if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) { fprintf(stderr, "set thread affinity failedn"); } CPU_ZERO(&get); if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) { fprintf(stderr, "get thread affinity failedn"); } for (j = 0; j < num; j++) { if (CPU_ISSET(j, &get)) { printf("thread %d is running in processor %dn", (int)pthread_self(), j); } } j = 0; while (j++ < 100000000) { memset(buf, 0, sizeof(buf)); } } pthread_exit(NULL); } int main(int argc, char *argv) { pthread_t tid; if (pthread_create(&tid, NULL, (void *)myfun, NULL) != 0) { fprintf(stderr, "thread create failedn"); return -1; } pthread_join(tid, NULL); return 0; }
php多線程教程?
PHP+shell實(shí)現(xiàn)多線程的方法
先寫個(gè)簡單的php代碼,這里為了讓腳本執(zhí)行時(shí)間更長,方便看效果,sleep一下,呵呵!先看下test.php的代碼:ls
PHP代碼:
for ($i=0;$i<10;$i++) {
echo $i;
sleep(10);
}
?>
在看下shell腳本的代碼,非常簡單
#!/bin/bash
for i in 1 2 3 4 5 6 7 8 9 10
do
/usr/bin/php -q /var/www/html/test.php &
done
注意到在請求php代碼的那行有一個(gè)&符號嗎,這個(gè)是關(guān)鍵,不加的話是不能進(jìn)行多線程的,&表示講服務(wù)推送到后臺(tái)執(zhí)行,因此,在 shell的每次的循環(huán)中不必等php的代碼全部執(zhí)行完在請求下一個(gè)文件,而是同時(shí)進(jìn)行的,這樣就實(shí)現(xiàn)了多線程,下面運(yùn)行下shell看下效果,這里你將 看到10個(gè)test.php進(jìn)程再跑,再利用linux的定時(shí)器,定時(shí)請求這個(gè)shell,在處理一些需要多線程的任務(wù),例如,批量下載時(shí),非常好用!
php中用WEB服務(wù)器實(shí)現(xiàn)多線程
假設(shè)我們現(xiàn)在運(yùn)行的是a.php這個(gè)文件. 但是我在程序中又請求WEB服務(wù)器運(yùn)行另一個(gè)b.php,那么這兩個(gè)文件將是同時(shí)執(zhí)行的.(PS: 一個(gè)鏈接請求發(fā)送之后, WEB服務(wù)器就會(huì)執(zhí)行它, 而不管客戶端是否已經(jīng)退出)
有些時(shí)候, 我們想運(yùn)行的不是另一個(gè)文件, 而是本文件中的一部分代碼.該怎么辦呢?
其實(shí)可是通過參數(shù)來控制a.php來運(yùn)行哪一段程序.
下面看一個(gè)例子:
//a.php,b.php
PHP代碼:--------------------------------------------------------------------------------
function runThread()
{
$fp = fsockopen('localhost', 80, $errno, $errmsg);
fputs($fp, "GET /b.php?act=brnrn"); //這里的第二個(gè)參數(shù)是HTTP協(xié)議中規(guī)定的請求頭
//不明白的請看RFC中的定義
fclose($fp);
}
function a()
{
$fp = fopen('result_a.log', 'w');
fputs($fp, 'Set in ' . Date('h:i:s', time()) . (double)microtime() . "rn");
fclose($fp);
}
function b()
{
$fp = fopen('result_b.log', 'w');
fputs($fp, 'Set in ' . Date('h:i:s', time()) . (double)microtime() . "rn");
fclose($fp);
}
if(!isset($_GET)) $_GET = 'a';
if($_GET == 'a')
{
runThread();
a();
}
else if($_GET == 'b') b();
?>
--------------------------------------------------------------------------------
打開result_a.log 和 result_b.log 比較一下兩個(gè)文件的中訪問的時(shí)間. 大家會(huì)發(fā)現(xiàn), 這兩個(gè)的確是在不同線程中運(yùn)行的.有些時(shí)間完全一樣.
上面只是一個(gè)簡單的例子, 大家可以改進(jìn)成其它形式.
既然PHP中也能多線程了, 那么問題也來了, 那就是同步的問題. 我們知道 PHP本身是不支持多線程的. 所以更不會(huì)有什么像Java 中synchronize的方法了. 那我們該如何做呢.
1. 盡量不訪問同一個(gè)資源. 以避免沖突. 但是可以同時(shí)像數(shù)據(jù)庫操作. 因?yàn)閿?shù)據(jù)庫是支持并發(fā)操作的. 所以在多線程的PHP中不要向同一個(gè)文件中寫入數(shù)據(jù). 如果必須要寫的話, 用別的方法進(jìn)行同步.. 如調(diào)用 flock對文件進(jìn)行加鎖等. 或建立臨時(shí)文件并在另外的線程中等待這個(gè)文件的消失 while(file_exits('xxx')); 這樣就等于這個(gè)臨時(shí)文件存在時(shí), 表示其實(shí)線程正在操作
如果沒有了這個(gè)文件, 說明其它線程已經(jīng)釋放了這個(gè).
2. 盡量不要從runThread在執(zhí)行fputs后取這個(gè)socket中讀取數(shù)據(jù). 因?yàn)橐獙?shí)現(xiàn)多線程, 需要的用非阻塞模式. 即在像fgets這樣的函數(shù)時(shí)立即返回.. 所以讀寫數(shù)據(jù)就會(huì)出問題. 如果使用阻塞模式的話, 程序就不算是多線程了. 他要等上面的返回才執(zhí)行下面的程序. 所以如果需要交換數(shù)據(jù)最后利用外面文件或數(shù)據(jù)中完成. 實(shí)在想要的話就用socket_set_nonblock($fp) 來實(shí)現(xiàn).
說了這么多, 倒底這個(gè)有沒有實(shí)際的意義呢? 在什么時(shí)候需要這種用這種方法呢 ?
答案是肯定的. 大家知道. 在一個(gè)不斷讀取網(wǎng)絡(luò)資源的應(yīng)用中, 網(wǎng)絡(luò)的速度是瓶頸. 如果采多這種形式就可以同時(shí)以多個(gè)線程對不同的頁面進(jìn)行讀取.
本人做的一個(gè)能從8848、soaso這些商城網(wǎng)站搜索信息的程序。還有一個(gè)從阿里巴巴網(wǎng)站上讀取商業(yè)信息和公司目錄的程序也用到了此技術(shù)。 因?yàn)檫@兩個(gè)程序都是要不斷的鏈接它們的服務(wù)器讀取信息并保存到數(shù)據(jù)庫。 利用此技術(shù)正好消除了在等待響應(yīng)時(shí)的瓶頸。
php模擬實(shí)現(xiàn)多線程的三種方法
PHP語言本身是不支持多線程的. 總結(jié)了一下網(wǎng)上關(guān)于PHP模擬多線程的方法, 總的來說, 都是利用了PHP的好伙伴們本身所具有的多線程能力. PHP的好伙伴指的就是LINUX和APACHE啦, LAMP嘛.
另外, 既然是模擬的, 就不是真正的多線程. 其實(shí)只是多進(jìn)程. 進(jìn)程和線程是兩個(gè)不同的概念. 好了, 以下方法都是從網(wǎng)上找來的.
1. 利用LINUX操作系統(tǒng)
for ($i=0;$i<10;$i++) {
echo $i;
sleep(5);
}
?>
上面存成test.php, 然后寫一段SHELL代碼
#!/bin/bash
for i in 1 2 3 4 5 6 7 8 9 10
do
php -q test.php &
done
2. 利用fork子進(jìn)程(其實(shí)同樣是利用LINUX操作系統(tǒng))
declare(ticks=1);
$bWaitFlag = FALSE; /// 是否等待進(jìn)程結(jié)束
$intNum = 10; /// 進(jìn)程總數(shù)
$pids = array(); /// 進(jìn)程PID數(shù)組
echo ("Startn");
for($i = 0; $i < $intNum; $i++) {
$pids = pcntl_fork();/// 產(chǎn)生子進(jìn)程,而且從當(dāng)前行之下開試運(yùn)行代碼,而且不繼承父進(jìn)程的數(shù)據(jù)信息
if(!$pids) {
// 子進(jìn)程進(jìn)程代碼段_Start
$str="";
sleep(5+$i);
for ($j=0;$j<$i;$j++) {$str.="*";}
echo "$i -> " . time() . " $str n";
exit();
// 子進(jìn)程進(jìn)程代碼段_End
}
}
if ($bWaitFlag)
{
for($i = 0; $i < $intNum; $i++) {
pcntl_waitpid($pids, $status, WUNTRACED);
echo "wait $i -> " . time() . "n";
}
}
echo ("Endn");
?>
3. 利用WEB SERVER, PHP不支持多線程, APACHE可是支持的, 呵呵.
假設(shè)我們現(xiàn)在運(yùn)行的是a.php這個(gè)文檔. 但是我在程式中又請求WEB服務(wù)器運(yùn)行另一個(gè)b.php
那么這兩個(gè)文檔將是同時(shí)執(zhí)行的.(代碼同上)
當(dāng)然啦,也可以把需要多線程處理的部分交給JAVA去處理, 然后在PHP里調(diào)用, 哈哈.
system('java multiThread.java');
?>
擴(kuò)展資料:PHP即“超文本預(yù)處理器”,是一種通用開源腳本語言。PHP是在服務(wù)器端執(zhí)行的腳本語言,與C語言類似,是常用的網(wǎng)站編程語言。PHP獨(dú)特的語法混合了C、Java、Perl以及 PHP 自創(chuàng)的語法。利于學(xué)習(xí),使用廣泛,主要適用于Web開發(fā)領(lǐng)域。
linux下C中怎么讓才能安全關(guān)閉線程?
這個(gè)問題,首先得搞清楚線程關(guān)閉或者退出有哪些方式
線程的退出方式
如果進(jìn)程中的任何線程調(diào)用exit,_Exit或_exit,則整個(gè)進(jìn)程終止。 類似地,當(dāng)信號的默認(rèn)操作是終止進(jìn)程時(shí),發(fā)送到線程的信號將終止整個(gè)進(jìn)程。單個(gè)線程可以有三種方式退出其控制流程,而不會(huì)終止整個(gè)進(jìn)程。
1線程可以簡單地從線程處理程序中返回,返回值是線程的退出代碼。
2該線程可以被同一進(jìn)程中的另一個(gè)線程取消。
3該線程可以調(diào)用pthread_exi
線程退出的返回值
#include <pthread.h> void pthread_exit(void *rval_ptr);
#include <pthread.h> int pthread_join(pthread_t thread, void **rval_ptr);pthread_join函數(shù)的rval_ptr參數(shù)是無類型指針。進(jìn)程中的其他線程可通過調(diào)用pthread_join函數(shù)來使用rval_ptr指針,調(diào)用它線程將阻塞,直到指定的線程調(diào)用pthread_exit或從其線程處理程序中返回或被取消。如果只是從其線程處理程序返回,則rval_ptr將包含返回碼。如果線程被取消,則rval_ptr指定的內(nèi)存位置設(shè)置為PTHREAD_CANCELED。
通過調(diào)用pthread_join,自動(dòng)會(huì)將加入的線程放置在分離狀態(tài),如果線程已處于分離狀態(tài),則pthread_join可能會(huì)失敗,返回EINVAL。如果我們對線程的返回值不感興趣,我們可以將rval_ptr設(shè)置為NULL。在這種情況下,調(diào)用pthread_join允許我們等待指定的線程,但不去檢索線程的終止?fàn)顟B(tài)。
下圖顯示了如何從已終止的線程中獲取退出代碼
運(yùn)行結(jié)果:
lj@lj-PC:~$ ./ptest
thread 1 returning
thread 2 exiting
thread 1 exit code 1
thread 2 exit code 2
線程如何取消
一個(gè)線程可以通過調(diào)用pthread_cancel函數(shù)請求取消同一進(jìn)程中的另一個(gè)。
#include <pthread.h>
int pthread_cancel(pthread_t tid);在默認(rèn)情況下,pthread_cancel將使tid指定的線程的行為就像它使用PTHREAD_CANCELED參數(shù)調(diào)用pthread_exit一樣。 但是,線程可以選擇忽略或以其他方式控制取消的方式。 請注意,pthread_cancel不會(huì)等待線程終止。
線程可以安排函數(shù)在退出時(shí)被調(diào)用,這些函數(shù)稱為線程清理處理程序。 可以為一個(gè)線程建立多個(gè)清理處理程序。 處理程序記錄在堆棧中,這意味著它們的執(zhí)行順序與它們注冊的順序相反。
#include <pthread.h>
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute);當(dāng)線程執(zhí)行以下操作之一時(shí),pthread_cleanup_push函數(shù)會(huì)被調(diào)用
調(diào)用pthread_exit
回復(fù)取消請求
使用非零執(zhí)行參數(shù)調(diào)用pthread_cleanup_pop
如果execute參數(shù)設(shè)置為零,則不會(huì)調(diào)用cleanup函數(shù)。 在任何一種情況下,pthread_cleanup_pop都會(huì)刪除最后一次調(diào)用pthread_cleanup_push所建立的清理處理程序。
下圖舉例如何使用線程清理處理程序。
運(yùn)行結(jié)果:
lj@lj-PC:~$ ./pclean
thread 1 start
thread 1 push complete
thread 2 start
thread 1 exit code 1
thread 2 push complete
cleanup: thread 2 second handler
cleanup: thread 2 first handler
thread 2 exit code 2
從輸出中,我們可以看到兩個(gè)線程都正常啟動(dòng)并退出,但只調(diào)用了第二個(gè)線程的清理處理程序。因此,如果線程是通過其處理函數(shù)直接返回而終止,則不會(huì)調(diào)用其清理處理程序,不過此行為在具體平臺(tái)實(shí)現(xiàn)之間會(huì)有所不同。另請注意,清理處理程序的調(diào)用順序與安裝它們的順序相反。
如果我們在FreeBSD或Mac OS X上運(yùn)行相同的程序,我們會(huì)發(fā)現(xiàn)該程序會(huì)導(dǎo)致段錯(cuò)誤。發(fā)生這種情況是因?yàn)樵谶@些系統(tǒng)上,pthread_cleanup_push實(shí)現(xiàn)為在堆棧上存儲(chǔ)某些上下文的宏。當(dāng)線程1在對pthread_cleanup_push的調(diào)用和對pthread_cleanup_pop的調(diào)用之間返回時(shí),堆棧被覆蓋,并且這些平臺(tái)在調(diào)用清理處理程序時(shí)嘗試使用此(已損壞的)上下文。在Single UNIX Specification中,在對pthread_cleanup_push和pthread_cleanup_pop的一對匹配調(diào)用之間返回會(huì)導(dǎo)致未定義的行為。在這兩個(gè)函數(shù)之間返回的唯一可移植方法是調(diào)用pthread_exit。
線程和進(jìn)程的類似操作
從上文我們可以看到線程和進(jìn)程的相似之處,見如下表格:
講了這么多,還有好多細(xì)節(jié)沒有講到,只要詳細(xì)的了解了這些細(xì)節(jié),我相信關(guān)于你的這個(gè)問題“l(fā)inux下C中怎么讓才能安全關(guān)閉線程”自然就有了答案。
uc編程什么意思?
UC編程指Unix 的系統(tǒng)函數(shù)和 Unix 系統(tǒng)的設(shè)計(jì)和管理機(jī)制
內(nèi)容包括:
1. Unix Linux 的靜態(tài)庫 和共享庫
2.C語言的錯(cuò)誤處理
3.環(huán)境變量和環(huán)境表
4.Unix Linux 的內(nèi)存管理
5.Unix Linux 的文件操作
6.Unix Linux 的目錄操作
7.Unix Linux 的進(jìn)程管理
8.Unix Linux 的信號處理
9.IPC - 進(jìn)程間通信(共享內(nèi)存,消息隊(duì)列)
10.Unix Linux 的網(wǎng)絡(luò)編程
11.Unix Linux 的多線程開發(fā)
總結(jié)
以上是生活随笔為你收集整理的linux c 多线程 popen(linux c 多线程)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常见的ddos攻击工具(不是ddos攻击
- 下一篇: 小米回应有品特殊激励需放弃年终奖……外媒