【Linux C | 进程】进程环境 | 什么是进程?进程的开始、终止、存储空间布局、命令行参数、环境变量

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭

本文未经允许,不得转发!!!


在这里插入图片描述

🎄一、概述

首先,我们了解什么是进程?
当代码编写后编译得到的可执行文件,就是程序,当程序运行起来后就是进程。也就是说,进程就是运行后的程序。

每个进程都有-一-个非负整型表示的唯一进程ID。因为进程D标识符总是唯一的,常将其用作其他标识符的一部分以保证其唯一性。
ID为0的进程通常是调度进程,常被成为交换进程(swapper);
ID为1的进程通常是init进程,在自举过程结束后,由内核调用。

查看进程

  • 1、简单方式
    ps :以简略方式显示当前控制终端的进程信息。
  • 2、复杂方式
    • ps -aux (linux中可用, unix中不支持)
      a: 显示所有用户控制终端的进程信息
      u: 以详尽方式显示
      x: 也显示那些无控制终端的进程信息
    • ps -elf (推荐使用, 具有通用性)
      e: 所有用户的进程
      l: 以长格式显示信息
      f: 按完整格式显示
  • 3、进程信息列表
    • UID : 进程属主
    • PID : 进程ID
    • PPID: 父进程ID
    • TTY: 该进程属于哪个终端
      tty1~tty6: 本机登录者
      pts/?? : 远程登录者
    • PRI, NI: 该进程的优先级 nice
    • S: 进程状态
      O—就绪
      R— 运行状态
      S— sleep
      Z— 僵尸

本文介绍进程的开始(main函数)、终止、存储空间布局、命令行参数、环境变量等。

在这里插入图片描述

🎄二、进程的开始、终止

✨2.1 main 函数

C程序总是从main函数开始执行。

当内核执行C程序时,在调用main前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址——这是由连接编辑器设置的,而连接编辑器则由C编译器调用。启动例程从内核取得命令行参数和环境变量值,然后为按上述方式调用main函数做好安排。

✨2.2 进程终止

有8种方式使进程终止(termination),其中5种为正常终止,它们是
(1)从main返回。
(2)调用exit。
(3)调用_exit或_Exit。
(4)最后一个线程从其启动例程返回。
(5)最后一个线程调用pthread_exit

异常终止有3种方式,它们是
(6)调用abort。
(7)接到一个信号并终止。
(8)最后一个线程对取消请求做出响应。

在这里插入图片描述

🎄三、程序的存储空间布局

一般,C程序一直由下面几个部分组成:

  • 正文段(text),也称代码段。这是由CPU执行的机器指令部分。通常,正文段是可共享的,所以即使是频繁执行的程序(如文本编辑器、C编译器和shell等)在存储器中也只需有一个副本,另外,正文段常常是只读的,以防止程序由于意外而修改其自身的指令。
  • 初始化数据段。通常将此段称为数据段,它包含了程序中需明确地赋初值的变量。例如,C程序中出现在任何函数之外的声明:
    int maxcount = 99 ;
    使此变量带有其初值存放在初始化数据段中。
  • 非初始化数据段。通常将此段称为bss段,这一名称来源于一个早期的汇编运算符,意思是“block started by symbol”(由符号开始的块),在程序开始执行之前,内核将此段中的数据初始化为0或空指针。出现在任何函数外的C声明
    longsum [1000] ;
    使此变量存放在非初始化数据段中。
  • 。自动变量以及每次函数调用时所需保存的信息都存放在此段中。每次调用函数时,其返回地址以及调用者的环境信息(例如某些机器寄存器的值)都存放在栈中。然后,最近被调用的函数在栈上为其自动和临时变量分配存储空间。通过以这种方式使用栈,可以递归调用C函数。递归函数每次调用自身时,就使用一个新的栈帧,因此一个函数调用实例中的变量集不会影响另一个函数调用实例中的变量。
  • 。通常在堆中进行动态存储分配。由于历史上形成的惯例,堆位于非初始化数据段和栈之间。

在这里插入图片描述

在这里插入图片描述

🎄四、命令行参数

当指向一个C程序时,在命令行给该程序传递参数。传递的参数可以在main函数的两个参数进行读取;

  • argc表示参数个数,程序名也算在参数里。
    ./a.out  # argc为 1,argv[0]就是a.out
    ./a.out command1 test line yes five #argc为 6
    
  • argv是一个char*数组,保存参数的字符串。argv[0]是程序名本身。
#include <stdio.h>
int main (int argc, char *argv [])
{
	int i;
	for (i = 0; i < argc; i++)
	{
		/* echo all command-line args */
		printf ( "argv [%d] : %s \n", i, argv[i] );
	}
	return (0) ;
}

在这里插入图片描述

在这里插入图片描述

🎄五、环境表、环境变量

✨5.1 环境表

每个程序都会接收到一张环境表。与参数表一样,环境表也是一个字符指针数组,其中每个指针包含一个以null结束的C字符串的地址。全局变量environ则包含了该指针数组的地址:

extern char **environ;

通常用getenvputenv函数来访问特定的环境变量,而不是用environ变量。但是,如果要查看整个环境,则必须使用environ指针。

在这里插入图片描述
看例子:

#include <stdio.h>
extern char **environ;
int main (int argc, char *argv [])
{
	int i;
	for (i = 0; *(environ+i)!=NULL; i++)
	{
		/* echo all command-line args */
		printf ( "environ[%02d]: %s \n", i, *(environ+i) );
	}
	return (0) ;
}

在这里插入图片描述

✨5.2 环境变量

ISO C定义了一个函数getenv,可以用其取环境变量值,但是该标准又称环境的内容是由实现定义的。

#include <stdlib.h>
char *getenv(const char *name);

getenv函数搜索环境列表以查找环境变量名,并返回一个指向相应值字符串的指针。

看例子:

#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv [])
{
	printf ( "HOME=[%s]\n", getenv("HOME"));
	printf ( "SHELL=[%s]\n", getenv("SHELL"));
	return (0) ;
}

在这里插入图片描述

🎄六、总结

本文介绍了什么是进程,进程的开始、结束,还有程序的存储空间布局,以及在main函数来获取命令行参数;最后结束环境表、环境变量。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wkd_007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值