守護進程daemon
守護進程概念就不贅述了,挺好理解的,從名字都能看出來。
查看
ps -ajx
其中TPGID為-1的代表daemon進程盟庞。
創(chuàng)建daemon進程有兩種方法:
方法1:
#include<unistd.h>
pid_t setsid(void);
當調(diào)用這個函數(shù)的時候不允許當前進程為進程組的Leader吃沪,所以一般都fork一個子進程。
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
void daemonize()
{
pid_t pid;
pid = fork();
if(pid > 0){
exit(0);
}else if(pid == 0){
setsid();
//改變工作目錄
chdir("/");
//下面將關(guān)閉終端和標準輸入輸出
close(0);
open("dev/null", O_RDONLY);
dup2(0, 1);
dup2(0, 2);
}
}
int main(void)
{
daemonize();
while(1){
//running
}
}
方法2:
使用庫函數(shù)daemon(man 3 daemon)來創(chuàng)建daemon進程什猖。
man 3 daemon看一下
#include <unistd.h>
int daemon(int nochdir, int noclose);
兩個參數(shù)的特別說明
If nochdir is zero, daemon() changes the process’s current working directory to the root directory ("/"); otherwise,
If noclose is zero, daemon() redirects standard input, standard output and standard error to /dev/null; otherwise, no changes are made to these file descriptors.
代碼就很簡單了
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main(void)
{
daemon(0, 0);
while(1){
//running
}
}
線程
線程概念也不再贅述了票彪。線程之間共享:
- 文件描述符
- 信號的處理方式
- 當前的工作目錄
- 用戶id和組id
不共享:
- 線程id
- 上下文,包括各種寄存器的值不狮、程序計數(shù)器和棧指針
- 椊抵空間
- errno 變量
- 信號屏蔽字
- 調(diào)度優(yōu)先級
創(chuàng)建線程
#include <pthread.h>
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void*), void *restrict arg);
注意:
在Linux上線程函數(shù)位于libpthread共享庫中,因此在編譯時要加上-lpthread選項
man 3 pthread_create 看一下
The pthread_create() function starts a new thread in the calling process.The new thread starts execution by invoking start_routine(); arg is passed as the sole argument of start_routine().
RETURN VALUE:On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.
意思大概是新啟動一個線程就會激活第3個參數(shù)所指向的函數(shù)摇零,最后一個參數(shù)是所激活函數(shù)的參數(shù)推掸。成功時返回0,否則返回錯誤編號驻仅。
線程的終止:
- 線程函數(shù)調(diào)用return谅畅,會終止當前線程,若是主線程噪服,則等同exit毡泻,會結(jié)束進程;
- pthread_cancel 終止同一進程中的其他線程;
- pthread_exit 終止自己的線程。
#include<pthread.h>
void pthread_exit(void *value_ptr);
這個函數(shù)的參數(shù)是可以通過函數(shù)pthread_join獲得粘优。
#include<pthread.h>
int pthread_join(pthread_t thread, void **value_ptr);
調(diào)用該函數(shù)的線程將掛起等待仇味,直到id為thread的線程終止。thread線程以不同的方法終止雹顺,通過pthread_join得到的終止狀態(tài)是不同的:
- 如果thread線程通過return返回丹墨,value_ptr所指向的單元里存放的是thread線程函數(shù)的返回值;
- 如果thread線程被別的線程調(diào)用pthread_cancel異常終止掉,value_ptr所指向的單元里存放的是常數(shù)PTHREAD_CANCELED;
- 如果thread線程是自己調(diào)用pthread_exit終止的嬉愧,value_ptr所指向的單元存放的是傳給pthread_exit的參數(shù)带到。
后面的線程同步異步的控制就不展開說了,在讀書的時候這塊是重點英染,都是算法揽惹。
下面寫個簡單例子驗證一下:
#include<stdio.h>
#include<pthread.h>
void *running()
{
pthread_t pid;
pid = pthread_self();
printf("thread,pid: 0x%u ,is running....\n", pid);
}
int main(void)
{
pthread_t ntid[3];
void *tret;
int i;
for(i=0; i<3; i++)
{
pthread_create(&ntid[i], NULL, running, NULL);
sleep(1);
}
pthread_join(ntid[0], &tret);
printf("thread 1,exit code %d\n", tret);
pthread_join(ntid[1], &tret);
printf("thread 2,exit code %d\n", tret);
pthread_cancel(ntid[2]);
pthread_join(ntid[2], &tret);
printf("thread 3,exit code %d\n", tret);
return 0;
}
附上運行截圖: