linux 进程控制

本文介绍了Linux操作系统中的进程概念,每个进程都有唯一的标识符——进程ID。同时,文章探讨了父子进程如何共享系统资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是进程

每一个进程在系统中都有唯一的ID标示它,此id为进程标示符

进程标示符的类型 pit_t,其实是一个无符号整形

一个进程标示符对应唯一的一个进程,多个进程标示符可以对应同一个程序

进程和程序的区别:
 程序:可运行的二进制代码文件,这种文件加载到内存中运行就得到了一个进程
 进程:同一个程序文件可以加载多次成为不同的进程
进程标示符和进程之间是一一对应关系,和程序文件是多对一关系!

进程中重要的id值
(1)进程ID(2)父进程ID(3)有效用户ID
(4)有效组ID(5)实际用户ID(6)实际组ID
其中进程id和父进程id的标示符不能更改

打印当前进程ID

#include<stdio.h>
#include<unistd.h>
int main()
 {
   pid_t pid,ppid,uid,euid,gid,egid;
   
    pid = getpid();
    pid = getppid();
    pid = getuid();
    pid = geteuid();
    pid = getgid(); 
    pid = getegid();   
    
    printf("id of current process: %u\n",pid);
    printf("parent id of current process:%u\n",ppid);
    printf("user id of current process:%u\n",uid);
    printf("effective user id of current process::%u\n",euid);
    printf("group id of current process:%u\n",gid);
    printf("effective group id of current process:%u\n",egid);


 }


创建一个进程
linux中用fork()函数创建一个新进程
linux系统中的任何一个进程都是由其他进程创建的,创建新进程的进程,即调用fork()函数的进程就是父进程,新创建的进程就是子进程
fork()函数的返回至是一个进程id,其返回值有3种情况
(1)对于父进程,fork()函数返回新创建的子进程的id 
(2)对于子进程,fork()函数返回0,由于系统的0号进程是内核进程,所以子进程的进程号不可能是0,由此区别父进程和子进程
(3)如果出错,fork函数返回1

打印父进程和子进程的id
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
  int main()
   {
    pid_t  pid;
    
    pid=fork();
    
     if(pid < 0 )
      {
       printf("fail to fork!\n");
       exit(1);
      }
     else if(pid == 0)
      {
       printf("this is child ,pid is :%u\n",getpid() );
      }
     else 
     {
       printf("this is parent ,pid is :%u,child-pid is :%u\n",getpid(),pid);
     
     } 
    return 0;
   }

父子进程共享资源:

(1)子进程完全复制了父进程的地址空间的内容,包括堆栈段和数据段的内容
(2)子进程没有复制代码段,而是和父进程共享代码段
(3)子进程的代码段是只读的,是可读的,因此父子进程可以共享代码段

验证子进程对父进程的影响

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

 int global;
 
 int main()
  {
   pid_t pid;
   int stack = 1 ;
   int *heap;
   
   heap=(int *)malloc(sizeof(int));
   *heap=2;
   pid=fork();
  if(pid < 0 )
      {
       printf("fail to fork!\n");
       exit(1);
      }
     else if(pid == 0)
      {
        global++;
        stack++;
        (*heap)++;
       printf("this is child ,data:%d,stack:%d,heap:%d\n",global,stack,*heap );
       
      }
     sleep(2);
     printf("this is child ,data:%d,stack:%d,heap:%d\n",global,stack,*heap );
   return 0;
  }

子进程对于数据段和堆栈段中的变量修改不能不能影响到父进程的进程环境

创建一个共享空间的子进程
vfork()函数用来创建一个公用父进程地址空间的子进程
(1)相当于创建了线程
(2)子进程一定比父进程先运行!

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>


 int global;
 
 int main()
  {
   pid_t pid;
   int stack = 1 ;
   int *heap;
   
   heap=(int *)malloc(sizeof(int));
   *heap=2;
   pid = vfork();
  if(pid < 0 )
      {
       printf("fail to fork!\n");
       exit(1);
      }
     else if(pid == 0)
      {
        global++;
        stack++;
        (*heap)++;
       printf("data:%d,stack:%d,heap:%d\n",global,stack,*heap );
       printf("child terminates\n");
      }
      
     //sleep(2);
     
     printf("data:%d,stack:%d,heap:%d\n",global,stack,*heap );
     printf("parent terminates\n");
   return 0;
  }

设置进程的所有者 

用 setuid(修改后的用户id)函数

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(void )
 {
   FILE *fp;
   uid_t uid;
   uid_t euid;
   
   uid=getuid();
   euid=getuid();
   printf("the uid is :%d\n",uid);
   printf("the euid is :%d\n",euid);
   
   if( setuid(1000) == -1 )
     {
       perror("fail to set uid");
       exit(1);
     }
     
   printf("after changing\n");
   uid=getuid();
   euid=getuid();
   printf("the uid is :%d\n",uid);
   printf("the euid is :%d\n",euid);
   
  return 0;
 }
  


输出进程统计信息


统计资源结构的指针的声明如下
struct rusage
{
   struct timeval ru_utime;//用户cpu时间
   struct timeval ru_stime;//系统cpu时间
   long  int ru_maxrss;//最大rss数量 
   long  int ru_ixrss;//与其他进程公用代码段的数目 
   struct timeval ru_utime; /* user time used */
   struct timeval ru_stime; /* system time used */
   long ru_maxrss;
   long ru_ixrss; /* XXX: 0 */
   long ru_idrss; /* XXX: sum of rm_asrss */
   long ru_isrss; /* XXX: 0 */
   long ru_minflt; /* any page faults not requiring I/O */
   long ru_majflt; /* any page faults requiring I/O */
   long ru_nswap; /* swaps */
   long ru_inblock; /* block input operations */
   long ru_oublock; /* block output operations */
   long ru_msgsnd; /* messages sent */
   long ru_msgrcv; /* messages received */
   long ru_nsignals; /* signals received */
   long ru_nvcsw; /* voluntary context switches */
   long ru_nivcsw; /* involuntary ” */

}

输出进程统计信息的目的:
运用此统计资源结构指针,可以得知程序的性能瓶颈,可以得出优化程序的解决方案!

此程序实现的是对子进程进行进程统计
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/resource.h>
 int main()
 {
  pid_t pid;
  struct rusage rusage;
  pid=fork();
  
  if( pid < 0 ) 
    {
     printf("fail to fork\n");
     exit(0);
    }
  else if(pid == 0) 
   {
     printf("the child!");
     exit(0);
   }
   else 
     printf("the parent\n");
     
  if( wait3(NULL,0,&rusage) == -1 )
    {
     perror("fail to wait!");
     exit(1);
    }
 
   printf("utime is %d\n",rusage.ru_utime);
   printf("ru_stime is %d\n",rusage.ru_stime);
   printf("ru_maxrss is %d\n",rusage.ru_maxrss);
   printf("ru_ixrss is %d\n",rusage.ru_ixrss);
   printf("ru_idrss is %d\n",rusage.ru_idrss);
   printf("ru_isrss is %d\n",rusage.ru_isrss);
   printf("ru_minflt is %d\n",rusage.ru_minflt);
   printf("ru_majflt is %d\n",rusage.ru_majflt);
   printf("ru_nswap is %d\n",rusage.ru_nswap);
   printf("ru_inblock is %d\n",rusage.ru_inblock);
   printf("ru_oublock is %d\n",rusage.ru_oublock);
   printf("ru_msgsnd is %d\n",rusage.ru_msgsnd);
   printf("ru_msgrcv is %d\n",rusage.ru_msgrcv);
   printf("ru_nsignals is %d\n",rusage.ru_nsignals);
   printf("ru_nvcsw is %d\n",rusage.ru_nvcsw);
   printf("ru_nivcsw is %d\n",rusage.ru_nivcsw);
  return 0;
 }

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值