Linux 進程與線程一(創建-關閉線程)


進程是一個實體。每一個進程都有他自己的內存地址段(heap,stack等等)
進程是執行中的程序。
程序是一個沒有生命的實體,只有處理器賦予程序生命時,它才能成為一個活動的實體。
進程是操作系統中最基本、重要的概念。
線程,又是被稱為輕量級進程(Lightweight Process LWP),是程序執行的最小單元。
每一個程序都至少有一個線程,若程序只有一個線程,那么就是程序本身。
單線程的進程可以簡單的認為只有一個線程的進程。
一個進程在同一時間只做一件事,有了多線程后一個進程同一時間可以做多件事。
每個線程可以處理不同的事務。
無論系統有幾個CPU,即使進程運行在單CPU上,多線程也可以是進程並發處理多個事務。
一個線程阻塞不會影響到另一個線程。
多線程的進程可以盡可能的利用系統CPU資源。
但也不是線程越多越好,線程越好,CPU分配給每個線程的時間片就越少。

 

線程包含了表示進程內執行環境必須的信息,包括標識線程的線程ID,一組寄存器值,棧,調度優先級和策略,信號屏蔽字,errno變量以及線程私有數據,
對於內存,堆內存和代碼區一般屬於一個進程的,但是棧卻是屬於一個線程的,每個線程都擁有一個獨立的棧errno也是屬於單個線程的,每個線程中的errno是獨立的。 進程內所有的信息對於線程都是共享的,包括執行代碼,全局變量,和堆內存,棧以及文件描述符。 線程標識
--就像每個進程有個進程ID一樣,線程也有自己的ID。 --進程ID用pid_t來表示,他是一個unsigned int. --線程可以通過pthread_t表示,pthread_t不能把它當整數處理。 --線程可以通過pthread_self()函數獲得自身的線程ID

 

線程創建
--在進程中只有一個控制線程 --程序開始運行的時候每個進程只有一個線程,它是以單線程方式啟動的,在創建多個線程以前,進程的行為與傳統的進程沒有區別
--gcc在鏈接的時候需要增加-lpthread選項(pthread是共享庫文件)。
--創建一個線程調用pthread_create函數。
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
如果pthread_create成功返回,有thread指向的內存單元被設置為新創建線程的線程ID。
attr參數用於定制各種不同的線程屬性。
新創建的線程從start_routine函數地址開始執行,該函數只有一個void *參數,
如果需要向start_routine函數傳遞多個參數,就需要把這些參數放到一個結構中,然后把這個結構的地址作為void
*傳入。 線程創建的時候不能保證哪個先運行。 pthread_create函數成功返回0,失敗返回非0,並且更新errno。 --注意:每個線程都擁有一份errno副本,不同的線程擁有不同的errno

 

//線程間的棧數據交互盲點
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <errno.h>
#include <pthread.h>

void * func(void *arg)
{
    int num=*(int *)arg;
    /*
      此時程序會報錯,無法獲取num的值
      這是因為num在線程的棧內存中,arg指針本來是threadcreate()函數中a和b的指針,
      但是a,b是個臨時變量,在控制線程的棧內存中,當執行完threadcreate()函數之后,變量a和b就會被系統釋放
      此時我們在另外一個線程中取a的值就變得不可預期,因為此時a有可能已經被釋放了,
      解決方案:可以在進程的堆內存上創建變量a和b,這樣在另一個線程中釋放,就沒有問題了
     */
    printf("num is %d\n",num);
    return NULL;
}

void threadcreate()
{
    pthread_t thr1,thr2;
    int a=1,b=2;
    if(pthread_create(&thr1,NULL,func,&a)!=0)
    {
        printf("create thread failed!\n");
        return;
    }
    if(pthread_create(&thr2,NULL,func,&b)!=0)
    {
        printf("create thread failed!\n");
        return;
    }
}


int main(int arg,char *args[])
{
    threadcreate();
    sleep(2);
    return 0;
}
.SUFFIXES:.c .o
CC=gcc
SRCS=tec01.c
OBJS=$(SRCS:.c=.o)
EXEC=tec

start:$(OBJS)
    $(CC) -lpthread -o $(EXEC) $(OBJS)
    @echo "^_^-----OK------^_^"
.c.o:
    $(CC) -Wall -g -o $@ -c $<
clean:
    rm -f $(OBJS)
    rm -f $(EXEC)

 

線程終止
--任一線程調用了exit函數,整個進程就會終止。
--如果信號默認動作是終止進程,那么信號發送到該進程,整個進程也會被終止。
單個線程通過以下三種方式退出
--線程只是從啟動函數中返回,返回值是線程的退出碼
--線程可以被同一進程中的其他線程取消。
--線程調用pthread_exit。
void pthread_exit(void * arg);
arg是個無類型指針,該指針會被其他線程調用pthread_join捕捉。
在線程的子函數中調用pthread_exit()函數,線程也會退出,這點跟exit()函數相同。
線程之間是異步的,無法確定哪個線程先執行。
進程內的信號捕捉一般在控制線程內進行
pthread_create()函數的第四個參數對應回調函數的參數

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM