Linux下進程代碼調試與理解
創建進程代碼1:
#include <stdio.h>
void main( ) {
int p1,p2;
while((p1=fork())==-1); /*創建子進程p1*/
if (p1==0) putchar('b');
else {
while((p2=fork())==-1); /*創建子進程p2*/
if(p2==0) putchar('c');
else putchar('a');
}
}
調試結果:
分析:這里的if和else不是以前理解的選擇分支。fork后產生的子進程和父進程並行運行的.這種理解是不正確的。if 和 else 還是選擇分支。 主要的原因是,fork() 函數調用一次,返回兩次。兩次返回的區別是:子進程的返回值是0,父進程返回值為新子進程的進程ID,至於abc順序為什么先后,偶也是懵的,只知道是隨機的。
創建進程代碼2:
#include <stdio.h>
void main( ) {
int p1,p2,i;
while((p1=fork())== -1); /*創建子進程p1*/
if (p1==0)
for(i=0; i<10; i++)
printf("daughter %d\n",i);
else {
while((p2=fork())== -1); /*創建子進程p2*/
if(p2==0)
for(i=0; i<10; i++)
printf("son %d\n",i);
else
for(i=0; i<10; i++)
printf("parent %d\n",i);
}
}
調試結果:
創建進程代碼3(在2上加上sleep):
#include <stdio.h>
void main( ) {
int p1,p2,i;
while((p1=fork())== -1); /*創建子進程p1*/
if (p1==0)
for(i=0; i<10; i++) {
printf("daughter %d\n",i);
sleep(1);
}
else {
while((p2=fork())== -1); /*創建子進程p2*/
if(p2==0)
for(i=0; i<10; i++) {
printf("son %d\n",i);
sleep(1);
}
else
for(i=0; i<10; i++) {
printf("parent %d\n",i);
sleep(1);
}
}
}
調試結果:
創建進程代碼4(在1上加上i觀察結果):
#include <stdio.h>
void main( ) {
int p1,p2;
int i;
while((p1=fork())==-1); /*創建子進程p1*/
if (p1==0) putchar('b');
else {
while((p2=fork())==-1); /*創建子進程p2*/
if(p2==0) putchar('c');
else putchar('a');
}
i++;
printf("i=%d\n",i);
}
調試結果:
可以觀察得出不同進程的i的值不同。
管理進程代碼:
#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
void main( )
{
int pid;
pid=fork( ); /*創建子進程*/
switch(pid)
{
case -1: /*創建失敗*/
printf("fork fail!\n");
exit(1);
case 0: /*子進程*/
execl("/bin/ls","ls","-1","-color",NULL);
printf("exec fail!\n");
exit(1);
default: /*父進程*/
wait(NULL); /*同步*/
printf("ls completed !\n");
exit(0);
}
}
調試結果:
如果缺少wait:
分析:少了個wait就會先是父進程執行completed后,子進程才把ls打印出來
如果目錄寫錯:
分析:父進程未出現錯誤仍正常運行,子進程報錯。
互斥程序代碼(加鎖):
#include <stdio.h>
#include <unistd.h>
void main() {
int p1,p2,i;
while((p1=fork( ))== -1); /*創建子進程p1*/
if (p1==0) {
lockf(1,1,0); /*加鎖,這里第一個參數為stdout(標准輸出設備的描述符)*/
for(i=0; i<10; i++)
printf("daughter %d\n",i);
lockf(1,0,0); /*解鎖*/
} else {
while((p2=fork( ))==-1); /*創建子進程p2*/
if (p2==0) {
lockf(1,1,0); /*加鎖*/
for(i=0; i<10; i++)
printf("son %d\n",i);
lockf(1,0,0); /*解鎖*/
} else {
lockf(1,1,0); /*加鎖*/
for(i=0; i<10; i++)
printf(" parent %d\n",i);
lockf(1,0,0); /*解鎖*/
}
}
}
互斥程序調試結果:
分析:lockf(1,1,0)是鎖定屏幕輸出,不讓其他進程可以輸出到屏幕,lockf(1,0,0)則是解鎖,所以拿到鎖的那個進程能夠在屏幕上一直輸出。
互斥程序代碼(未加鎖):
#include <stdio.h>
#include <unistd.h>
void main() {
int p1,p2,i;
while((p1=fork( ))== -1); /*創建子進程p1*/
if (p1==0) {
//lockf(1,1,0); /*加鎖,這里第一個參數為stdout(標准輸出設備的描述符)*/
for(i=0; i<10; i++)
printf("daughter %d\n",i);
//lockf(1,0,0); /*解鎖*/
} else {
while((p2=fork( ))==-1); /*創建子進程p2*/
if (p2==0) {
//lockf(1,1,0); /*加鎖*/
for(i=0; i<10; i++)
printf("son %d\n",i);
//lockf(1,0,0); /*解鎖*/
} else {
//lockf(1,1,0); /*加鎖*/
for(i=0; i<10; i++)
printf(" parent %d\n",i);
//lockf(1,0,0); /*解鎖*/c
}
}
}
運行結果:
分析:沒有鎖,他們是同步運行,順序不分先后。
互斥程序代碼(加鎖+sleep):
#include <stdio.h>
#include <unistd.h>
void main() {
int p1,p2,i;
while((p1=fork( ))== -1); /*創建子進程p1*/
if (p1==0) {
lockf(1,1,0); /*加鎖,這里第一個參數為stdout(標准輸出設備的描述符)*/
for(i=0; i<10; i++){
printf("daughter %d\n",i);
sleep(1);
}
lockf(1,0,0); /*解鎖*/
} else {
while((p2=fork( ))==-1); /*創建子進程p2*/
if (p2==0) {
lockf(1,1,0); /*加鎖*/
for(i=0; i<10; i++){
printf("son %d\n",i);
sleep(1);
}
lockf(1,0,0); /*解鎖*/
} else {
lockf(1,1,0); /*加鎖*/
for(i=0; i<10; i++){
printf(" parent %d\n",i);
sleep(1);
}
printf(" parent %d\n",i);
lockf(1,0,0); /*解鎖*/
}
}
}
運行結果:
分析:加上sleep也是一樣的,他們是同步運行的。