Linux系统编程:step1( 二 )

#include#include#include#includeint main(int argc,const char* argv[]){pid_t pid;for(int i=0;i<4;i++){printf("---------------i=%d\n",i);}pid = fork();if(pid >0){printf("parent process,pid=%d\n",getpid());}else if(pid ==0){printf("childprocess,pid=%d\n",getpid());}for(int i=0;i<4;i++){printf("---------------i=%d\n",i);}return 0;}
有上面实验的结果可知,子进程中是从fork下面的开始开始执行的 。所以子进程虽然有代码段,但是不会执行 。让父进程睡一会(父进程结束的太快了,已经结束了,使得子进程将init进程作为父进程了)
出现上面的原因:
2、ps和kill命令
Q:如何获取当前进程的id?
A:
#
#
#
#
#
#
int main(int argc, const char* argv[])
while(1)
(“hello,world\n”);
sleep(1);
0;
TTY :就是终端,au显示依赖终端的选项 。
Q:终端对于进程来说有什么用呢?
A:没有终端就看不到输出,所以依赖终端的进程是需要和用户交互的 。
|:表示管道 。
kill:发信号给某个进程
只需学1-31个信号即可 。
杀死某个进程:kill -9 (仅为9号信号为表示杀死信号)
3、进程间数据共享
关于fork,刚fork之后,两个地址空间用户区数据完全相同,后续各自都做了各自不同的操作,各个进程的地址空间中的数据是完全独立的,如下图所示,n=24子、父一样的,在子父进程各自对n进行操作时,是互不影响的,一个++,一个–;扩展:研究这个n = 24,但对于这个n只是进行读操作时,那么在物理内存中n是一份,也就是子父进程只是读这个n,而不改变,这样可以节省内存,也就是读时共享n;但是在进行读写操作时,因为可以子父进程可以修改它,为了子父进程互不影响,子进程就拷贝一份,也就是不是共享的 。
上图所示,在父或子进程对变量进行写操作时,都会在物理内存开辟一块内存保存修改的值,而且父子变量内存不共享 。
Q:父、子进程之间,是否可以通过一个全局变量进行通信?
A:不能,因为根据上面的原理,写复制,父子各自的变量物理内存不一样,所以内存不能共享 。
小结:读时共享,写时复制
扩展:需要实现共享就牵涉到进程间的通信 。
4、exec函数族
(1)作用
①让父子进程执行不相干的操作
②父子进程代码段一样的,而exec函数组可以替换父子空间的源代码,也就是.text段
注意:替代.text中代码的是可执行文件源代码,因为是进程,所以需要是可执行的程序 。其中的ls是一个例子,它是shell中的一个可执行文件,所以当替换只有,进程就相当于执行命令ls了 。鸠占鹊巢的感觉 。
(2)使用
例子:
“who canhere”,只执行了一次,并且是在父进程3047中,而子进程3048执行的程序是ls,所以得出结论,当子进程使用execl()时,子进程中的.text中的源代码全部被execl程序中的代码所替换,也就不能执行if(pid==0)外的内容了 。
5、进程回收
(1)孤儿进程
①爹生孩子
②爹先死,孩子还活着,孩子就叫做孤儿进程
③孤儿被init进程领养,init进程变为孤儿进程的父亲 。(这就是为什么写程序会出现子进程的父进程变为1,也就是原来的父进程执行的太快了,以至于原来父进程结束了,而子进程还没执行完,就成孤儿了 。)
④为了释放子进程占用的系统资源
进程结束之后,能够释放用户区空间;释放不了PCB,必须由父进程释放(key) 。
这里就出现了孤儿进程被ppid=1的进程领养了 。
(2)僵尸进程
①孩子死了,爹还活着,爹不去释放子进程的pcb,孩子就变成 了僵尸进程 。(因为只能由父进程释放)