㈠ c語言如何編寫一個簡單的多線程程序
這是一個多線程例子,裡面只有兩個線程,是生產者/消費者模式,已編譯通過,注釋很詳細,
如下:
/* 以生產者和消費者模型問題來闡述linux線程的控制和通信你
生產者線程將生產的產品送入緩沖區,消費者線程則從中取出產品。
緩沖區有N個,是一個環形的緩沖池。
*/
#include <stdio.h>
#include <pthread.h>
#define BUFFER_SIZE 16
struct prodcons
{
int buffer[BUFFER_SIZE];/*實際存放數據的數組*/
pthread_mutex_t lock;/*互斥體lock,用於對緩沖區的互斥操作*/
int readpos,writepos; /*讀寫指針*/
pthread_cond_t notempty;/*緩沖區非空的條件變數*/
pthread_cond_t notfull;/*緩沖區未滿 的條件變數*/
};
/*初始化緩沖區*/
void pthread_init( struct prodcons *p)
{
pthread_mutex_init(&p->lock,NULL);
pthread_cond_init(&p->notempty,NULL);
pthread_cond_init(&p->notfull,NULL);
p->readpos = 0;
p->writepos = 0;
}
/*將產品放入緩沖區,這里是存入一個整數*/
void put(struct prodcons *p,int data)
{
pthread_mutex_lock(&p->lock);
/*等待緩沖區未滿*/
if((p->writepos +1)%BUFFER_SIZE ==p->readpos)
{
pthread_cond_wait(&p->notfull,&p->lock);
}
p->buffer[p->writepos] =data;
p->writepos++;
if(p->writepos >= BUFFER_SIZE)
p->writepos = 0;
pthread_cond_signal(&p->notempty);
pthread_mutex_unlock(&p->lock);
}
/*從緩沖區取出整數*/
int get(struct prodcons *p)
{
int data;
pthread_mutex_lock(&p->lock);
/*等待緩沖區非空*/
if(p->writepos == p->readpos)
{
pthread_cond_wait(&p->notempty ,&p->lock);//非空就設置條件變數notempty
}
/*讀書據,移動讀指針*/
data = p->buffer[p->readpos];
p->readpos++;
if(p->readpos == BUFFER_SIZE)
p->readpos = 0;
/*設置緩沖區未滿的條件變數*/
pthread_cond_signal(&p->notfull);
pthread_mutex_unlock(&p->lock);
return data;
}
/*測試:生產站線程將1 到1000的整數送入緩沖區,消費者線程從緩沖區中獲取整數,兩者都列印信息*/
#define OVER (-1)
struct prodcons buffer;
void *procer(void *data)
{
int n;
for( n=0;n<1000;n++)
{
printf("%d ------>\n",n);
put(&buffer,n);
}
put(&buffer,OVER);
return NULL;
}
void *consumer(void *data)
{
int d;
while(1)
{
d = get(&buffer);
if(d == OVER)
break;
else
printf("----->%d\n",d);
}
return NULL;
}
int main()
{
pthread_t th_p,th_c;
void *retval;
pthread_init(&buffer);
pthread_create(&th_p,NULL,procer,0);
pthread_create(&th_c,NULL,consumer,0);
/*等待兩個線程結束*/
pthread_join(th_p, &retval);
pthread_join(th_c,&retval);
return 0;
}
㈡ linux創建多線程輸出abcde
創建多線程 - 落日鋼琴家的博客 - CSDN博客 - linux創建多線程
2021年3月28日最簡單的Linux下創建線程的例子 使用pthread_create函數 編譯的時候結尾處多加 -pthread ...
CSDN編程社區
Linux多線程 - Ustinian%的博客 - CSDN博客 - linux創建多線程
5月24日只創建task_struct,將那個創建出來的進程的task_struct和父進程的task_struct共享虛擬地址空間...
CSDN編程社區
㈢ 在Linux下用C++創建新線程
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void* thread(void* arg)
{
printf ("The child process...\n");
}
int main(int argc, char *argv[])
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,(void *)thread,NULL);
if(ret!=0)
{
printf ("Create pthread error!\n");
exit (1);
}
}
程序如上就可以編譯。
它屬於linux下C編程中多線程編程的范圍。
用命令
gcc -lpthread 1.c -o 1
./1
就可以出結果。
多線程編程的基礎可以參考
http://hi..com/huifeng00/blog/item/ed13ddc0d6c59c170ff47715.html
㈣ Linux多線程編程
程序代碼test.c共兩個線程,一個主線程,一個讀緩存區的線程:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char globe_buffer[100];
void *read_buffer_thread(void *arg); //這里先聲明一下讀緩存的線程,具體實現寫在後面了
int main()
{
int res,i;
pthread_t read_thread;
for(i=0;i<20;i++)
globe_buffer[i]=i;
printf("\nTest thread : write buffer finish\n");
sleep(3);\\這里的3秒是多餘,可以不要。
res = pthread_create(&read_thread, NULL, read_buffer_thread, NULL);
if (res != 0)
{
printf("Read Thread creat Error!");
exit(0);
}
sleep(1);
printf("waiting for read thread to finish...\n");
res = pthread_join(read_thread, NULL);
if (res != 0)
{
printf("read thread join failed!\n");
exit(0);
}
printf("read thread test OK, have fun!! exit ByeBye\n");
return 0;
}
void *read_buffer_thread(void *arg)
{
int i,x;
printf("Read buffer thread read data : \n");
for(i=0;i<20;i++)
{
x=globe_buffer[i];
printf("%d ",x);
globe_buffer[i]=0;//清空
}
printf("\nread over\n");
}
---------------------------------------------------------------------------------
以上程序編譯:
gcc -D_REENTRANT test.c -o test.o –lpthread
運行這個程序:
$ ./test.o:
㈤ Linux多線程編程
編譯時要用到pthread 庫:gcc -lpthread
錯誤碼位置:/usr/include/asm-generic/errno.h
gcc pthread_create.c -lpthread
思考:主子線程交替列印奇數偶數。
思考:證明線程可以自己取消自己。
思考:證明SIGKILL和SIGSTOP 是無法阻塞的。
/usr/include/bits/pthreadtypes.h中查看pthread_mutex_t
思考:用多線程將一個文件1.c拷貝3個副本,11.c,12.c,13.c
思考:多個生產者和消費者
思考:將互斥量等初始化使用pthread_once實現。
思考:設置線程的分離屬性,然後在新縣城中獲取自己的分離屬性。
㈥ linux c 編寫一個多線程。。。
多線程程序的編寫,是和操作系統和語言都有關系的。
1。首先,操作系統需要支持多線程,很久之前的古老的操作系統是不支持多任務多線程的。當然,當前的操作系統都是支持多線程的。但是,不同的操作系統具體如何支持的細節是不太一樣的,也有效率之別。
2。語言方面,
2.1 C/C++在語言本身是不支持多線程開發的,但是能夠進行API調用;同時現在有很多C++方面的庫,通常也是跨平台的,比如Boost,OpenMP,MPI之類;
vc2010在2010年4月12號發布了,vc2010裡面微軟增加了一個並行開發的庫。
2.2 C#和Java在語言本身層面上就支持多線程開發了。說得更直接一些,就是語言函數庫里提供了封裝包,用起來很方便。
多線程開發,其實最關鍵的是操作系統層面的運作機理。Windows和unix/linux上很多概念是相似的,但是有些細節方面是有所出入的。需要針對操作系統,學習內部機制。
開發庫,開發語言都是相對次要的一個層面。可以選擇你喜歡的語言。
因為操作系統底層API的不同,如果直接調用API開發,那肯定不會就有移植性的。但是現在有一些庫(比如Boost)是可移植的,基於這些庫就可以達到可移植。
用C/C++在Windows和Linux下面編寫多線程程序,概念是相通的,具體細節是有一些差別的。但是你在windows上很有經驗了之後,再在Linux上做,肯定很快就能搞定的。
㈦ c語言實現多線程
Linux操作系統,C語言實現多線程
Windows操作系統,C語言實現多線程
Windows下的多線程(不帶停止)
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void*ThreadOne(void*threadArg)
{
printf("線程開始啦,參數是:%s ",(char*)threadArg);
returnNULL;
}
intmain(void)
{
pthread_tThreadID;/*記錄線程標識符*/
void*waitingResult;/*等待線程退出的等待結果*/
interrorCode;/*記錄線程的錯誤代碼*/
char*aMessage="這是線程的參數";
/*創建並啟動線程ThreadOne。若返回值非零,則線程創建失敗*/
errorCode=pthread_create(&ThreadID,NULL,ThreadOne,aMessage);
if(errorCode!=0)
{
printf("線程ThreadOne創建失敗。錯誤代碼:%d ",errorCode);
returnEXIT_FAILURE;
}
/*等待線程標識符為的ThreadID的線程結束*/
errorCode=pthread_join(ThreadID,&waitingResult);
if(errorCode!=0)
{
printf("等待線程退出等待失敗。錯誤代碼:%d ",errorCode);
returnEXIT_FAILURE;
}
printf("線程的返回值是%p ",waitingResult);
returnEXIT_SUCCESS;
}
#include<stdio.h>
#include<windows.h>
DWORDAPIENTRYThreadOne(LPVOIDthreadArg)
{
printf("線程開始啦,參數是:%s ",(char*)threadArg);
return0;
}
intmain(void)
{
HANDLEhThread;/*記錄線程句柄*/
DWORDThreadID;/*記錄線程ID號*/
DWORDwaitingResult;/*等待線程退出的等待結果*/
DWORDthreadExitCode;/*記錄線程的返回值*/
char*aMessage="這是線程的參數";
/*創建並啟動線程ThreadOne,返回值為線程句柄,賦值給hThread*/
hThread=CreateThread(NULL,0L,ThreadOne,(LPVOID)aMessage,0L,&ThreadID);
if(hThread==NULL)
{
printf("線程ThreadOne創建失敗。錯誤代碼:%lu ",GetLastError());
returnEXIT_FAILURE;
}
/*等待線程句柄為的hThread線程結束*/
waitingResult=WaitForSingleObject(hThread,INFINITE);
if(waitingResult==WAIT_FAILED)
{
printf("等待線程退出等待失敗。錯誤代碼:%lu ",GetLastError());
returnEXIT_FAILURE;
}
if(GetExitCodeThread(hThread,&threadExitCode))
printf("線程的返回值是%lu ",threadExitCode);
else
printf("獲取線程的返回值獲取失敗。錯誤代碼:%lu ",GetLastError());
returnEXIT_SUCCESS;
}
#include<stdio.h>
#include<windows.h>
DWORDWINAPIoxianchen(LPVOIDlpParam);
intmain(intargc,char*argv[])
{
intnum=0;
CreateThread(NULL,NULL,oxianchen,&num,NULL,NULL);
while(1)
{
num++;
printf("主線程!%05d ",nu***eep(40);
}
return0;
}
DWORDWINAPIoxianchen(LPVOIDlpParam)
{
int*a=lpParam;
while(1)
{
++*a;
printf("副線程!%05d0x%p ",*a,a);
Sleep(80);
}
return0;
}
㈧ linux系統下,c語言pthread多線程編程傳參問題
3個線程使用的都是同一個info
代碼 Info_t *info= (Info_t *)malloc(sizeof(Info_t));只創建了一個info
pthread_create(&threads[i],NULL,calMatrix,(void *)info); 三個線程使用的是同一個
我把你的代碼改了下:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
intmtc[3]={0};//resultmatrix
typedefstruct
{
intprank;
int*mta;
int*mtb;
}Info_t;
void*calMatrix(void*arg)
{
inti;
Info_t*info=(Info_t*)arg;
intprank=info->prank;
fprintf(stdout,"calMatrix:prankis%d ",prank);
for(i=0;i<3;i++)
mtc[prank]+=info->mta[i]*info->mtb[i];
returnNULL;
}
intmain(intargc,char**argv)
{
inti,j,k=0;
intmta[3][3];
intmtb[3]={1};
Info_t*info=(Info_t*)malloc(sizeof(Info_t)*3);
for(i=0;i<3;i++)
for(j=0;j<3;j++)
mta[i][j]=k++;
/*3threads*/
pthread_t*threads=(pthread_t*)malloc(sizeof(pthread_t)*3);
fprintf(stdout," ");fflush(stdout);
for(i=0;i<3;i++)
{
info[i].prank=i;
info[i].mta=mta[i];
info[i].mtb=mtb;
pthread_create(&threads[i],NULL,calMatrix,(void*)(&info[i]));
}
for(i=0;i<3;i++)
pthread_join(threads[i],NULL);
fprintf(stdout," ====thematrixresult==== ");
fflush(stdout);
for(i=0;i<3;i++)
{
fprintf(stdout,"mtc[%d]=%d ",i,mtc[i]);
fflush(stdout);
}
return0;
}
矩陣的計算我忘記了,你運行看看結果對不對
㈨ 求思路:linux C上多線程接收數據怎麼進行存儲
在Linux系統中使用C/C++進行多線程編程時,我們遇到最多的就是對同一變數的多線程讀寫問題,大多情況下遇到這類問題都是通過鎖機制來處理,但這對程序的性能帶來了很大的影響,當然對於那些系統原生支持原子操作的數據類型來說,我們可以使用原子操作來處理,這能對程序的性能會得到一定的提高。那麼對於那些系統不支持原子操作的自定義數據類型,在不使用鎖的情況下如何做到線程安全呢?本文將從線程局部存儲方面,簡單講解處理這一類線程安全問題的方法。
一、數據類型
在C/C++程序中常存在全局變數、函數內定義的靜態變數以及局部變數,對於局部變數來說,其不存在線程安全問題,因此不在本文討論的范圍之內。全局變數和函數內定義的靜態變數,是同一進程中各個線程都可以訪問的共享變數,因此它們存在多線程讀寫問題。在一個線程中修改了變數中的內容,其他線程都能感知並且能讀取已更改過的內容,這對數據交換來說是非常快捷的,但是由於多線程的存在,對於同一個變數可能存在兩個或兩個以上的線程同時修改變數所在的內存內容,同時又存在多個線程在變數在修改的時去讀取該內存值,如果沒有使用相應的同步機制來保護該內存的話,那麼所讀取到的數據將是不可預知的,甚至可能導致程序崩潰。
如果需要在一個線程內部的各個函數調用都能訪問、但其它線程不能訪問的變數,這就需要新的機制來實現,我們稱之為Static memory local to a thread (線程局部靜態變數),同時也可稱之為線程特有數據(TSD: Thread-Specific Data)或者線程局部存儲(TLS: Thread-Local Storage)。這一類型的數據,在程序中每個線程都會分別維護一份變數的副本(),並且長期存在於該線程中,對此類變數的操作不影響其他線程。如下圖:
二、一次性初始化
在講解線程特有數據之前,先讓我們來了解一下一次性初始化。多線程程序有時有這樣的需求:不管創建多少個線程,有些數據的初始化只能發生一次。列如:在C++程序中某個類在整個進程的生命周期內只能存在一個實例對象,在多線程的情況下,為了能讓該對象能夠安全的初始化,一次性初始化機制就顯得尤為重要了。——在設計模式中這種實現常常被稱之為單例模式(Singleton)。Linux中提供了如下函數來實現一次性初始化:
#include <pthread.h>
// Returns 0 on success, or a positive error number on error
int pthread_once (pthread_once_t *once_control, void (*init) (void));
利用參數once_control的狀態,函數pthread_once()可以確保無論有多少個線程調用多少次該函數,也只會執行一次由init所指向的由調用者定義的函數。init所指向的函數沒有任何參數,形式如下:
void init (void)
{
// some variables initializtion in here
}
另外,參數once_control必須是pthread_once_t類型變數的指針,指向初始化為PTHRAD_ONCE_INIT的靜態變數。在C++0x以後提供了類似功能的函數std::call_once (),用法與該函數類似。使用
㈩ linux用戶空間 - 多進程編程(三)
管道用於有學園關系的進程之間。
管道的pipe 系統調用實際上就是創建出來兩個文件描述符。
當父進P1程創建出 fd[2] 時,子進程P2 會繼承父進程的所有,所以也會得到pipe 的 2個 文件描述符。
所以毫無瓜葛的兩個進程,一定不會訪問到彼此的pipe。無法用管道進行通信。
管道一般是單工的。f[0]讀,f[1]寫
管道也可以適用於 兄弟進程(只要有血緣即可)。由於管道是單工的,當兩個進程之間需要雙向通信,則需要兩跟管道。
執行
ctrl-c(2號信號) + SIGUSR1 信號 綁了一個新函數。則 ctrl-c 無效。
查看進程的信號
號信號被捕獲。
將2號信號忽略掉
9號信號 kill 和19號信號 stop 不能亂搞,只能用預設。
其它信號甚至段信號也都可以捕獲。
改變程序的執行現場,修改PC指針,有些像goto,只不過返回非0值
運行結果
making segment fault
after segment fault
程序不會死。
如果不忽略 page fault
則會產生 core mp.
不停的給data 賦值,同時每隔1s會有信號進來,列印 data的值。
理論上列印出來的結果同時為0,同時為1
但並非如此,是 0,1,交替隨機的。
signal 非同步的,隨時都可以進來,所以列印出來的結果,並不是我想要的。
信號對於應用程序來說,很像中斷對於內核,都是訪問臨界區數據
信號被屏蔽,延後執行。
寫多線程的程序時,不要以為只有線程之間有競爭,其實信號也會有競爭
system v 的IPC 年代有些久遠。
有血緣關系的進程 key_t 都是相同的。
Key 是私有key IPV PRIVATE
可能用消息隊列,可能用共享內存,可能用信號量進行通訊。
利用 _pathname 路徑,約定好一條路徑。和tcp/ip地址很像,來生成一個key_t key, 用msg_get shm_get 得到共享內存or 信號量。
int id 可以理解為文件描述符 fd。
其中Sys V 的共享內存 最為常用。
一定要檢查路徑,如果僅僅有2個進程,你沒有創建路徑,兩者都是 -1(相當於大家約定好了),那當然能通信拉。但更多的進程出現,則會有問題。
一定要檢查返回值
依然依靠key,但是api 實在是太挫了。P&V 操作都是 semop. (posix 的 ipc跟為簡潔)
POSIX 共享內存當然也需要一個名字,但並不是路徑。
無論讀進程還是寫進程,都需要傳入相同的名字。
如果是unbuntu 會在以下路徑生成文件
其實 2和3 是1 的符號鏈接。 只要保證是一個就能互相通信
關鍵點,mmap 內存的屬性修改為 private 後,產生寫時,虛擬地址一樣,但是物理地址已經不同了
當然 如果子進程修改了程序背景,執行了 exec,那麼完全不一樣了,直接修改了內存邏輯。