進程基本知識
- 進程標識符 pid
類型pid_t
命令ps
ps axf
ps axm
ps ax -L
進程號是順次向下使用(fd是使用最小的fd)
getpid();
getppid();
- 進程的產生
復制進程并創(chuàng)建進程,執(zhí)行1次拢军,返回2次
fork()
注意理解關鍵字:duplicating,意味著拷貝惫确,克隆山上,一模一樣等含義。
fork后父子進程的區(qū)別:fork的返回值不一樣英支,pid不同佩憾,ppid也不同,未決信號和文件鎖不繼承干花,資源利用量清0
init進程:1號妄帘,是所有進程的祖先進程
調度器的調度策略來決定哪個進程先運行
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t pid;
printf("[%d]Begin!\n",getpid());
//非常重要 ,輸出設備默認是行緩沖區(qū)池凄,所以會默認fflush抡驼。但是重定向文件./fork >/tmp/out是全緩沖模式 ,父子進程都有begin所以打印兩次 .fork之前必須fflush
fflush(NULL);
//pid =0表示子進程 pid>0表示父進程
pid = fork();
if(pid<0)
{
perror("fork()");
}
if(pid==0)
{
printf("[%d]:Child is working!",getpid());
}
else
{
printf("[%d]:Parent is working!",getpid());
}
printf("End");
//getchar();
exit(0);
}
有可能是父進程先調度或者子進程先被調度
輸出結果:
如果我們把輸出現在在重定向文件上肿仑,則會出現兩次的begin致盟。這是因為輸出設備默認是行緩沖區(qū),所以會默認fflush尤慰。但是重定向文件./fork >/tmp/out是全緩沖模式 馏锡,父子進程都有begin所以打印兩次,且子進程也是打印父進程的pid .fork之前必須fflush
- fork出的子進程和父進程都對應同一個內存數據對象伟端。誰如果要對該數據對象進行寫的操作杯道,就自己復制一個內存數據對象,稱為寫時拷貝责蝠,誰寫誰拷貝党巾,然后影響的只是自己進程所指向的對象萎庭。
- 進程的消亡及釋放資源
wait(int *status) 等待進程狀態(tài)發(fā)生變化
waitpid(pid_t pid,int *status,int options)
waitid()
wait3()
wait4() - exec函數族 當執(zhí)行這個函數的時候,該函數族執(zhí)行的二進制文件將替換原有的進程齿拂,原有進程的內容都不執(zhí)行驳规,而是執(zhí)行exec里的內容。
execl();
execlp();
execle();
execv();
execvp();
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t pid;
puts("Begin!");
fflush(NULL);
fork();
if(pid<0)
{
perror("fork()");
exit(1);
}
if(pid==0)
{
//子進程返回0创肥,父進程返回子進程的pid
execl("/bin/date","date","+%s",NULL);
//如果子進程執(zhí)行execl失敗則會繼續(xù)執(zhí)行下面的代碼
perror("execl");
exit(1);
}
//父進程等待子進程返回达舒,替他收尸
wait(NULL);
puts("End!");
exit(0);
}
注意:在執(zhí)行exec函數族之前,也必須先執(zhí)行fflush(NULL)函數進行刷新緩沖區(qū)叹侄。
image.png
- 用戶權限及組權限
setid()
setreuid()
setregid()
seteuid()
setegid() - 觀摩課:解釋器文件
- system();
- 進程會計
acct() - 進程時間
times() - 守護進程
查看進程命令:ps -axj
一般指系統(tǒng)開機就會自動運行的進程巩搏。守護進程的父進程即ppid=1,pid=pgid=sid
會話session趾代,標識sid
終端
setsid() //創(chuàng)建守護進程
getpgrp()
getpgid()
setpgid()
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FNAME "/tmp/out"
//守護進程例子
static int daemonize(void)
{
int fd;
pid_t pid;
pid = fork();
if(pid<0)
{
perror("fork()");
return -1;
}
if(pid>0)
{
exit(0); //parent
}
fd = open("/dev/null",O_RDWR);
if(fd<0)
{
perror("open()");
return -1;
}
//重定向到0 1 2
dup2(fd,0);
dup2(fd,1);
dup2(fd,2);
if(fd>2)
{
close(fd);
}
//脫離控制終端贯底,父進程也結束了,那他的父進程就會變成1號init進程(守護進程的ppid=1)
setsid();
chdir("/");
//不會產生文件了撒强,就不給權限了禽捆。
umask(0);
return 0;
}
int main()
{
File *fp;
if(daemonize())
{
exit(1);
}
fp = fopen(FNAME,"w");
if(fp==NULL)
{
perror("fopen()");
exit(1);
}
for(i=0;;i++)
{
fprintf(fp,"%d\n",i);
fflush(fp);
sleep(1);
}
exit(0);
}
- 系統(tǒng)日志