fork与namespace

本文深入探讨了Linux中fork和exec系统调用的使用,以及它们如何与命名空间结合,为进程提供隔离环境。详细解释了upid结构如何跟踪进程ID,并介绍了cgroup、IPC、网络、挂载、PID、用户和UTS等不同类型命名空间的作用。

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

fork的使用

fork用于创建子进程,而exec可以替换子进程执行的代码。

一个简单的例子:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h>  
#include <stdlib.h> 
#include <errno.h>   
#include <sys/wait.h> 
  
int main(){ 
   pid_t  pid; 
   int ret = 1; 
   int status; 
   pid = fork(); 
   if (pid == -1){ 
  
      // pid == -1 means error occured 
      printf("can't fork, error occured\n"); 
      exit(EXIT_FAILURE); 
   } 
   else if (pid == 0){ 
  
      // pid == 0 means child process created 
      // getpid() returns process id of calling process 
      printf("child process, pid = %u\n",getpid()); 
  
      // the argv list first argument should point to   
      // filename associated with file being executed 
      // the array pointer must be terminated by NULL  
      // pointer 
      char * argv_list[] = {"ls","-lart","/home",NULL}; 
  
      // the execv() only return if error occured. 
      // The return value is -1 
      execv("ls",argv_list); 
      exit(0); 
   } 
   else{ 
      // a positive number is returned for the pid of 
      // parent process 
      // getppid() returns process id of parent of  
      // calling process 
      printf("parent process, pid = %u\n",getppid()); 
  
        // the parent process calls waitpid() on the child 
        // waitpid() system call suspends execution of  
        // calling process until a child specified by pid 
        // argument has changed state 
        // see wait() man page for all the flags or options 
        // used here  
        if (waitpid(pid, &status, 0) > 0) { 
              
            if (WIFEXITED(status) && !WEXITSTATUS(status))  
              printf("program execution successfull\n"); 
              
            else if (WIFEXITED(status) && WEXITSTATUS(status)) { 
                if (WEXITSTATUS(status) == 127) { 
  
                    // execv failed 
                    printf("execv failed\n"); 
                } 
                else 
                    printf("program terminated normally,"
                       " but returned a non-zero status\n");                 
            } 
            else 
               printf("program didn't terminate normally\n");             
        }  
        else { 
           // waitpid() failed 
           printf("waitpid() failed\n"); 
        } 
      exit(0); 
   } 
   return 0; 
} 

Namespace相关

Linux kernel now tracks process’s PIDs using upid structure instead of a single pid value. The upid structure tells about the pid and the namespaces where that pid is valid.

struct upid {
	int nr;			/* moved from struct pid */
	struct pid_namespace *ns;	/* the namespace this value
						 * is visible in
						 */
	...
    };
    struct pid {
	atomic_t count;
	struct hlist_head tasks[PIDTYPE_MAX];
	struct rcu_head rcu;
	int level;		/* the number of upids */
	struct upid numbers[0];
    };

Types of namespaces

Linux provides following namespaces:

  • cgroup:This isolates Cgroup root directory(CLONE_NEWCGROUP)
  • IPC: isolates System V IPC, POSIX message queues(CLONE_NEWIPC)
  • Network: isolates Network devices, ports etc(CLONE_NEWNET)
  • Mount: isolates mountpoints(CLONE_NEWNS)
  • PID: isolated process IDs(CLONE_NEWPID)
  • User : isolates User and group IDs(CLONE_NEWUSER)
  • UTS: isolates Hostname and NIS domain name(CLONE_NEWUTS)

As part of namespace management, Linux provides below APIs:

clone()- plain old clone() creates a new process. If we pass one or more CLONE_NEW* flags to clone(),then new namespaces are created for each
flag, and the child process is made a member of those
namespaces.
setns()- allows a process to join an existing namespace. The namspace is specified by a file descriptor reference to one of proc/[pid]/nsfiles.
unshare()- moves calling process to a new namespace created according to CLONE_NEW* arguments. More than one such flags can be specified.

Note:For PID namespace, clone() MUST be called as that can be created only while a new process is created. Spawned process as a result of clone() has pid 1. For PID namespace , unshare() wont be useful.

参考文献

  • https://josedonizetti.github.io/cni/namespace/bridge/linux/network/2017/10/22/container-networking-bridge.html
  • https://itnext.io/chroot-cgroups-and-namespaces-an-overview-37124d995e3d
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值