Linux下C對進程的操作


我將通過代碼的方式說明一些進程的基本操作

獲取當前進程的ID 和父進程ID
#include<stdio.h>                                                                              
#include<unistd.h> //包含我們進程相關的系統調用                                                
int main(int argc,char* *argv){                                                                
        pid_t my_pid,parent_pid; //pid_t是我們進程號的宏定義                                   
        my_pid = getpid();//getpid()獲取當前進程的ID                                         
        parent_pid = getppid();//獲取父進程ID                                                            
        printf("my_pid = %d\n",my_pid);                                                        
        printf("parent_pid = %d\n",parent_pid);                                                
        return 0;                                                                              
}

執行結果
在這裏插入圖片描述
我們還可以通過查看父進程看下我們的程序是哪一個進程創建的。調用命令ps -ef | grep 20524得到結果-bash啦
在這裏插入圖片描述

進程的創建

linux系統中創建進程採用fork系統調用,fork出來的進程除了pid其他的和父進程一樣。爲了區分父進程和子進程我們需要判斷fork的返回值。失敗返回-1,如果是父進程則返回子進程的ID,子進程就會返回0。如果沒聽明白的話。我們試想一下,父進程P與子進程C的程序是一樣的,我們創建C肯定是爲了執行不一樣的任務。一樣的代碼如何執行不同的任務?所以就需要fork的返回值()來做分支判斷。如果是0說明當前運行的是子進程C,就調用fork==0的分支,否則當前就是父進程在運行,就執行其他的。下面看代碼:

#include<unistd.h>                                                                             
#include<sys/types.h>                                                                          
#include<stdio.h>                                                                              
#include<errno.h>                                                                              
int main(int argc,char* * argv){                                                               
        pid_t child;                                                                           
        printf("父進程ID = %d\n",getpid());                                                    
        child = fork();                                                                        
        if (child == -1){                                                                                
                printf("fork error\n");                                                        
        }else if(child == 0){                                                                  
                printf("子進程ID = %d\n",getpid());                                            
                sleep(5);                                                                      
                exit(0);                                                                       
        }else{                                                                                 
                sleep(10);                                                                     
                printf("parent again\n");                                                      
                exit(0);                                                                       
        }                                                                                      
}

執行結果
在這裏插入圖片描述
我們剛纔說到了根據fork()返回值判斷是子進程還是父進程,那麼我們創建了子進程過後。如何執行不同的程序呢?可以使用exec族的系統調用,共有六個函數

  • int execl(const char *path, const char *arg, …);
  • int execlp(const char *file, const char *arg, …);
  • int execle(const char *path, const char *arg, …, char *const
    envp[]);
  • int execv(const char *path, char *const argv[]);
  • int execvp(const char *file, char *const argv[]);
  • int execve(const char *path, char *const argv[], char *const envp[]);

調用exec時進程被新的執行程序替代,然後從main開始執行,下面我們看一個例子:
創建test.c testexec.c文件,通過testexec.c中創建的子進程調用test的可執行文件,代碼如下:

#test.c文件
#include<stdio.h>                                                                                        
#include<string.h>                                                                             
main(){                                                                                        
        int a,b,c;                                                                             
        int *p = NULL;                                                                         
                                                                                               
        a = 1;                                                                                 
        b =  2;                                                                                
        c = a+++b;                                                                             
        p = &c;                                                                                
        printf("*p = %d\n",*p);                                                                
}
#testexec.c文件
#include<unistd.h>                                                                             
#include<sys/types.h>                                                                          
#include<stdio.h>                                                                              
#include<errno.h>                                                                              
int main(int argc,char* * argv){                                                               
        pid_t child;                                                                           
        printf("父進程ID = %d\n",getpid());                                                    
        child = fork();                                                                        
        if (child == -1){                                                                      
                printf("fork error\n");                                                        
        }else if(child == 0){                                                                  
                printf("子進程ID = %d\n",getpid());                                            
                sleep(2);                                                                      
                execl("/root/gdbtest/exec/test",NULL);//執行同目錄下的test文件                 
                printf("執行execl失敗\n");//如果調用失敗輸出                                             
                exit(0);                                                                       
        }else{                                                                                 
                printf("parent again\n");                                                      
                exit(0);                                                                       
        }                                                                                      
}

從下圖的執行結果我們可以看到成功的調用的test文件並且輸出了3
在這裏插入圖片描述

進程間的通信

我們都知道進程間的通信包括管道、信號量、共享內存、消息隊列、Socket的方式,但是我們可能都停留在理論的層面,所以用消息隊列來做個實踐。我們可以使用ipcs查看系統IPC
在這裏插入圖片描述
可以通過msgget()建立或者訪問消息隊列,通過msgsnd和msgrcv發送讀取消息
通過一個例子說明,包括消息發送端和消息接受端

#發送端的程序,模擬消息隊列的發送操作
#include<stdio.h>                                                                              
#include<stdlib.h>                                                                             
#include<unistd.h>                                                                             
#include<pthread.h>                                                                            
#include<fcntl.h>                                                                              
#include<sys/types.h>                                                                          
#include<sys/ipc.h>                                                                            
#include<sys/msg.h>                                                                            
#include<errno.h>                                                                              
struct my_msg{                                                                                 
  long int my_msg_type;                                                                        
  char text[BUFSIZ];                                                                           
 }                                                                                             
main(void){                                                                                    
        int running = 1;                                                                       
        int msgid;                                                                             
        struct my_msg msgbuf;                                                                  
        msgid = msgget((key_t)1234,0666|IPC_CREAT);                                                   
        if (msgid == -1){                                                                      
          printf("message error\n");                                                           
          exit(1);
          }                                                                                      
        while(running){                                                                        
                printf("enter some test:\n");                                                  
                fgets(msgbuf.text,BUFSIZ,stdin);                                               
                msgbuf.my_msg_type = 1;                                                        
                if(msgsnd(msgid,(void*)&msgbuf,BUFSIZ,0) == -1){                               
                        printf("msg send error\n");                                            
                        exit(1);                                                               
                }                                                                              
                if(strncmp(msgbuf.text,"end",3) == 0){                                         
                  running = 0;                                                                 
                }                                                                              
                                                                                               
        }                                                                                      
        exit(0);                                                                               
} 
#模擬消息的接受
#include<stdio.h>                                                                                     
#include<stdlib.h>                                                                             
#include<unistd.h>                                                                             
#include<pthread.h>                                                                            
#include<fcntl.h>                                                                              
#include<sys/types.h>                                                                          
#include<sys/ipc.h>                                                                            
#include<sys/msg.h>                                                                            
#include<errno.h>                                                                              
struct my_msg{                                                                                 
  long int my_msg_type;                                                                        
  char text[BUFSIZ];                                                                           
 }                                                                                             
main(void){                                                                                    
        int running = 1;                                                                       
        int msgid;                                                                             
        struct my_msg msgbuf;                                                                  
        long int msg_to_receive = 0;                                                           
        msgid = msgget((key_t)1234,0666|IPC_CREAT);                                            
        if (msgid == -1){                                                                      
          printf("message error\n");
          printf("message error\n");                                                           
          exit(1);                                                                             
        }                                                                                      
        while(running){                                                                        
                if(msgrcv(msgid,(void*)&msgbuf,BUFSIZ,msg_to_receive,0) == -1){                
                  printf("msg receive error\n");                                               
                  exit(1);                                                                     
                }                                                                              
                printf("%s\n",msgbuf.text);                                                    
                if(strncmp(msgbuf.text,"end",3) == 0){                                         
                  running = 0;                                                                 
                }                                                                              
        }                                                                                      
        if(msgctl(msgid,IPC_RMID,0) == -1)                                                     
        {                                                                                      
          printf("msg del error \n");                                                          
          exit(1);                                                                             
        }                                                                                      
        exit(0);                                                                               
}

最後我們運行程序看看效果
輸入前:
在這裏插入圖片描述
在這裏插入圖片描述
輸入後
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章