15、深入理解计算机系统笔记:进程控制-阿里云开发者社区

开发者社区> hopegrace> 正文

15、深入理解计算机系统笔记:进程控制

简介: 1、获取进程ID[1] 每个进程都有一个唯一的正数(非0)进程ID(PID)。 示例代码 #include #include pid t getpid(void); pid t getppid(void); returns: PID of either the caller...
+关注继续查看

1、获取进程ID[1]

每个进程都有一个唯一的正数(非0)进程IDPID)。

示例代码

#include <unistd.h>
#include <sys/types.h>
pid t getpid(void);
pid t getppid(void);
returns: PID of either the caller or the parent

    The getpid and getppid routines return an integer value of type pid_t, which on Linux systems

is defined in types.h as an int.

进程总是处于运行,停止,终止三种状态间。

2、创建和终止

示例代码

#include <stdlib.h>
void exit(int status);
this function does not return

#include <unistd.h>
#include <sys/types.h>
pid t fork(void);
returns: 0 to child, PID of child to parent, -1 on error

#include <sys/types.h>
#include <sys/wait.h>
pid t waitpid(pid t pid, int *status, int options);
returns: PID of child if OK, 0 (if WNOHANG) or -1 on error
The members of the wait set are determined by the pid argument:
 If pid > 0, then the wait set is the singleton child process whose process ID is equal to pid.
 If pid = -1, then the wait set consists of all of the parent’s child processes.

    The newly created child process is almost, but not quite, identical to the parent. The child

gets an identical (but separate) copy of the parents userlevel virtual address space, including the text, data,

and bss segments, heap, and user stack. The child also gets identical copies of any of the parents open file descriptors, which

means the child can read and write any files that were open in the parent when it called fork. The most significant

difference between the parent and the newly created child is that they have different

PIDs.

fork函数常令人迷惑,因为它只被调用一次,却会返回两次:一次是在调用进程(父进程)中,一次是在新创建的子进程中。

示例见原文中。

3、回收子进程

进程终止时,内核并不是立即把它从系统中清除;而是保持一种终止状态,直到被父进程回收(reaped)。父进程回收已终止的子进程时,内核将子进程的退出状态传递给父进程,然后抛弃已终止的进程。一个终止了但仍未被回收的进程称为僵尸进程(zombie)。

如果父进程没有回收,则通过init进程来回收。

一个进程通过调用waitpid函数来等待它的子进程终止或暂停。

4、进程休眠

示例代码

#include <unistd.h>
unsigned int sleep(unsigned int secs);
returns: seconds left to sleep
//让进程挂起一段时间
#include <unistd.h>
int pause(void);
always returns -1
//puts the calling function to sleep until a signal is received by the process.

5、加载并运行程序

示例代码

#include <unistd.h>
int execve(char *filename, char *argv[], char *envp);
does not return if OK, returns -1 on error
int main(int argc, char **argv, char **envp);
int main(int argc, char *argv[], char *envp[]);

execve加载了filename之后,启动代码准备栈,并将控制传递给新程序的主函数,函数原形如代码中所示。

wps_clip_image-29702wps_clip_image-2126

wps_clip_image-29705

通过getenv,setenv,unsetenv来设备环境变量。

6、进程是执行中程序的一个特殊实例;程序总是运行在某个进程的上下文中。fork函数在新的子进程中运行相同的程序,新的子进程是父进程的一个复制品;execve函数在当前进程的上下文中加载并运行一个新的程序,它会覆盖当前进程的地址空间,但并没有创建一个新进程,新的程序仍然有相同的PID,并且继承了调用execve函数时打开的所有文件描述符。

示例代码

/* $begin shellmain */
#include "csapp.h"
#define MAXARGS   128

/* function prototypes */
void eval(char*cmdline);
int parseline(char *buf, char **argv);
int builtin_command(char **argv); 

int main() 
{
    char cmdline[MAXLINE]; /* command line */

    while (1) {
	/* read */
	printf("> ");                   
	Fgets(cmdline, MAXLINE, stdin); 
	if (feof(stdin))
	    exit(0);

	/* evaluate */
	eval(cmdline);
    } 
}
/* $end shellmain */
  
/* $begin eval */
/* eval - evaluate a command line */
void eval(char *cmdline) 
{
    char *argv[MAXARGS]; /* argv for execve() */
    char buf[MAXLINE];   /* holds modified command line */
    int bg;              /* should the job run in bg or fg? */
    pid_t pid;           /* process id */
    
    strcpy(buf, cmdline);
    bg = parseline(buf, argv); 
    if (argv[0] == NULL)  
	return;   /* ignore empty lines */

    if (!builtin_command(argv)) { 
	if ((pid = Fork()) == 0) {   /* child runs user job */
	    if (execve(argv[0], argv, environ) < 0) {
		printf("%s: Command not found.\n", argv[0]);
		exit(0);
	    }
	}

	/* parent waits for foreground job to terminate */
	if (!bg) {
	    int status;
	    if (waitpid(pid, &status, 0) < 0)
		unix_error("waitfg: waitpid error");
	}
	else
	    printf("%d %s", pid, cmdline);
    }
    return;
}

/* if first arg is a builtin command, run it and return true */
int builtin_command(char **argv) 
{
    if (!strcmp(argv[0], "quit")) /* quit command */
	exit(0);  
    if (!strcmp(argv[0], "&"))    /* ignore singleton & */
	return 1;
    return 0;                     /* not a builtin command */
}
/* $end eval */

/* $begin parseline */
/* parseline - parse the command line and build the argv array */
int parseline(char *buf, char **argv) 
{
    char *delim;         /* points to first space delimiter */
    int argc;            /* number of args */
    int bg;              /* background job? */

    buf[strlen(buf)-1] = ' ';  /* replace trailing '\n' with space */
    while (*buf && (*buf == ' ')) /* ignore leading spaces */
	buf++;

    /* build the argv list */
    argc = 0;
    while ((delim = strchr(buf, ' '))) {
	argv[argc++] = buf;
	*delim = '\0';
	buf = delim + 1;
	while (*buf && (*buf == ' ')) /* ignore spaces */
	       buf++;
    }
    argv[argc] = NULL;
    
    if (argc == 0)  /* ignore blank line */
	return 1;

    /* should the job run in the background? */
    if ((bg = (*argv[argc-1] == '&')) != 0)
	argv[--argc] = NULL;

    return bg;
}
/* $end parseline */

<Computer Systems:A Programmer's Perspective>

注:[1] 原书8.4节有详细的论述。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
计算机网络学习笔记(1)概述
一、因特网的组成 (1) 边缘部分:由所有链接在因特网的主机(end system 终端)组成。 (2) 核心部分:由大量网络和连接这些网络的路由器组成。 二、两种通信方式 (1) 客户--服务器方式(C/S) (2) 对等方式(P2P) 三、分组交换 1、在发送端,先把较长的报文划分成较短的、固定长度的数据段,每一个数据段前面添加一个首部构成分组。接收端则把收到的数据恢复成
1114 0
Linux运行与控制后台进程的方法:nohup, setsid, &, disown, screen
我们经常会碰到这样的问题,用ssh登录了远程的Linux服务器,运行了一些耗时较长的任务,结果却由于网络等的不稳定导致任务中途失败。这是由于在用户注销(logout)或者网络断开时,终端会收到 HUP(hangup)信号从而关闭其所有子进程。
967 0
(二十九)java条件控制语句培训笔记
<p><span style="color:#8080FF">java</span><span style="color:#8080FF">结构控制语句示例:</span><span style="color:#8080FF">if</span><span style="color:#8080FF">,</span><span style="color:#8080FF">if else,s
1010 0
书接前文,用多进程模式实现fibonnachi并发计算
#coding: utf-8 import logging import os import random import sys import time import re # import requests # import concurrent.
824 0
《逻辑与计算机设计基础(原书第5版)》——1.2 计算机系统设计的抽象层次
本节书摘来自华章计算机《逻辑与计算机设计基础(原书第5版)》一书中的第1章,第1.2节,作者:(美)M.莫里斯·马诺(M. Morris Mano)著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1717 0
深入理解计算机系统结构——并发编程
并发编程 如果逻辑控制流在实际上重叠,那么它们就是并发的,这种常见的现象称为并发,出现在计算机系统的许多不同层面上。 应用级并发在其他情况下也是很有用的: 访问慢速I/O设备。 与人交互。 通过推迟工作以降低延迟。
743 0
阿里ECS进阶课程学习笔记--基于ECS搭建FTP服务
FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。在开发网站的时候,通常利用FTP协议把网页或程序传到Web服务器上。默认情况下FTP协议使用TCP端口中的 20和21这两个端口,其中20用于传输数据,21用于传输控制信息。
163 0
+关注
698
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载