linux c 笔记 进程控制(一)

1.进程简述
   进程是一个动态的实体,操作系统资源分配的基本单位,每个进程都有一个非负整型的唯一进程 ID。因为进程 ID标识符总是唯一的,常将其用做其他标识符的一部分以保证其唯一性。
    1)进程标识:
    每个进程都有一个非负整型的唯一进程 ID。因为进程 ID标识符总是唯一的,常将其用做其他标识符的一部分以保证其唯一性。tmpnam 函数将进程 ID作为名字    的一部分创建一个唯一的路径名。
    有某些专用的进程:进程 ID 0是调度进程,常常被称为交换进程 ( swapper )。该进程并不执行任何磁盘上的程序—它是内核的一部分,因此也被称为系统进程。进程 ID 1通常是 init进程,在自举过程结束时由内核调用。该进程的程序文件在 UXIX的早期版本中是 / etc / init,在较新版本中是/ sbin / init。此进程负责在内核自举后起动一个 UNIX系统。init通常读与系统有关的初始化文件( / etc / rc * 文件),并将系统引导到一个状态 (例如多用户)。init进程决不会终止。它是一个普通的用户进程 (与交换进程不同,它不是内核中的系统进程 ),但是它以超级用户特权运行。在某些U N I X的虚存实现中,进程ID 2 是页精灵进程( pagedaemon )。此进程负责支持虚存系统的请页操作。与交换进程一样,页精灵进程也是内核进程。

除了进程I D,每个进程还有一些其他标识符。下列函数返回这些标识符。
    
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void); 返回:调用进程的进程 ID
pid_t getppid(void);返回:调用进程的父进程 ID
uid_t getuid(void); 返回:调用进程的实际用户 ID
uid_t geteuid(void); 返回:调用进程的有效用户 ID
gid_t getgid(void); 返回:调用进程的实际组 ID
gid_t getegid(void); 返回:调用进程的有效组 ID

2.linux 的进程状态:
 1).运行状态 2).可中断等待状态 3).不可中断等待状态 4).僵死状态 5).停止状态

3.进程控制:
•  fork:用与创建一个新进程
• exit:用于终止进程
• exec:用于执行一个进程
• wait:将父程序挂起,等待子程序终止
• getpid:获取当前进程的进程ID
•  nice:改变进程的优先级

• 代码段:
由 CPU执行的机器指令部分。通常,代码段是可共享的 ,在存储器中也只需有一个副本,另外,代码段常常是只读的,以防止程序由于意外事故而修改其自身的指令,父子程序共享代码段,此外子进程还获得父进程数据堆,段栈的复制.
初始化数据段:
通常将此段称为数据段,它包含了程序中需赋初值的变量。例如, C程序中任何函数之外的说明:   int maxcount = 99;   使此变量以初值存放在初始化数据段中。
• 非初始化数据段:
通常将此段称为 bss段,这一名称来源于早期汇编程序的一个操作符,意思是“block started by symbol(由符号开始的块)”,在程序开始执行之前,内核将此段初始化为0。函数外的说明: long   sum[1000] ;  使此变量存放在非初始化数据段中。
• 栈:
自动变量以及每次函数调用时所需保存的信息都存放在此段中。每次函数调用时,其返回地址、以及调用者的环境信息(例如某些机器寄存器)都存放在栈中。然后,新被调用的函数在栈上为其自动和临时变量分配存储空间。通过以这种方式使用栈, C函数可以递归调用。用于函数调用,保存函数的返回地址,函数的参数,函数内部定义的局部定量.,
• 堆:
通常在堆中进行动态存储分配。

4.创建进程
    1).fork函数
一个现存进程调用 fork函数是UNIX内核创建一个新进程的唯一方法 (这并不适用于前节提
及的交换进程、 init进程和页精灵进程。这些进程是由内核作为自举过程的一部分以特殊方式
创建的)。
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
返回:子进程中为 0,父进程中为子进程 ID,出错为- 1 (创建失败的原因在于父程序拥有的子程序的个数超过了规定的限制,error=EAGAIN ,若是可供使用的内存不足也会导致创建失败,此时error = ENOMEM )
     由fork创建的新进程被称为子进程( child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是 0,而父进程的返回值则是新子进程的进程 ID。将子进程 ID返回给父进程的理由是:因为一个进程的子进程可以多于一个,所以没有一个函数使一个进程可以获得其所有子进程的进程 ID。fork使子进程得到返回值 0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用 getppid以获得其父进程的进程 ID (进程ID 0总是由交换进程使用,所以一个子进程的进程ID不可能为0 )。
     子进程和父进程继续执行 fork之后的指令。子进程是父进程的复制品。例如,子进程获得父进程数据空间、堆和栈的复制品。注意,这是子进程所拥有的拷贝。父、子进程并不共享这些存储空间部分。如果正文段是只读的,则父、子进程共享正文段 .
     现在很多的实现并不做一个父进程数据段和堆的完全
    1.子程序有自己唯一的ID
    2.fork的返回值不同,父进程返回子进程的ID ,子进程则为0
    3.不同的父进程ID.子进程的父进程ID为创建他的父进程ID.
    4.子进程共享父进程打开的文件描述符,但父进程对文字描述符的改变不会影响子进程中的文件描述符.
    5.子进程不继承父进程设置的文件锁
    6.子进程不继承父进程的设置的警告
    7.子进程的未决信号集被清空

fork有两种用法:
    一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待委托者的服务请求。当这种请求到达时,父进程调用 fork,使子进程处理此请求。父进程则继续等待下一个服务请求。
 一个进程要执行一个不同的程序。这对 shell是常见的情况。在这种情况下,子进程在
从fork返回后立即调用exec 。
    某些操作系统将 (2)中的两个操作( fork之后执行 exec )组合成一个,并称其为 spawn。UNIX将这两个操作分开,因为在很多场合需要单独使用 fork,其后并不跟随 exec。另外,将这两个操作分开,使得子进程在 fork和exec之间可以更改自己的属性。例如 I/O重新定向、用户 ID、信号排列等。

vfork函数
    vfork函数的调用序列和返回值与fork相同,但两者的语义不同。
    vfork用于创建一个新进程,而该新进程的目的是 e x e c一个新程序 。 vfork与fork一样都创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用 exec (或exit),于是也就不会存访该地址空间。不过在子进程调用 exec或exit之前,它在父进程的空间中运行。这种工作方式在某些 U N I X的页式虚存实现中提高了效率
    vfork和fork之间的另一个区别是: vfork保证子进程先运行,在它调用 exec或exit之后父进程才可能被调度运行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)

    所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

时间: 2024-10-27 16:50:13

linux c 笔记 进程控制(一)的相关文章

linux c 笔记 进程控制(三)

进程退出    进程结束表示进程即将结束运行,在linux系统中进程的退出方法分为正常退出和异常退出两种.exit函数进程有三种正常终止法及两种异常终止法.(1) 正常终止:    (a) 在main函数内执行return语句.这等效于调用 exit.    (b) 调用exit函数.此函数由ANSI C定义,其操作包括调用各终止处理程序(终止处理程序在调用atexit函数时登录),然后关闭所有标准I/O流等.因为ANSI C并不处理文件描述符.多进程(父.子进程)以及作业控制,所以这一定义对

linux c 笔记 进程控制(二)---守护进程

守护进程(Daemon),一说精灵进程,是指在后台运行的,没有控制终端与之相连的程序.它独立于控制终端周期性地执行某种任务或等待处理某些发生的事件.它是一个生存期较长的进程,守护进程常常在系统引导装入时启动,在系统关闭时终止.Linux系统有很多守护进程,大多数服务都是通过守护进程实现的,同时,守护进程还能完成许多系统任务,例如,作业规划进程crond.打印进程lqd等(这里的结尾字母d就是Daemon的意思).由于在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的

linux c 笔记 进程控制(四)

一.更改用户 I D和组I D可以用setuid函数设置实际用户ID和有效用户ID.与此类似,可以用 setgid函数设置实际组ID和有效组ID.int setgid(gid_t gid) ;两个函数返回:若成功则为 0,若出错则为- 1关于谁能更改 ID有若干规则.现在先考虑有关改变用户 I D的规则(在这里关于用户 ID所说明的一切都适用于组 ID).(1) 若进程具有超级用户特权,则 setuid函数将实际用户 ID.有效用户 ID,以及保存的设置-用户- ID设置为uid.(2) 若进程

linux 命令及进程控制

main.c  main.o/main.obj  main/main.exe          编译                连接 程序运行;      两步: gcc/g++  -c  main.c/main.cpp  -> main.o              gcc/g++ -o main  main.o -> main(可执行文件)     一步:  gcc -o main mian.c  -> main    工程文件:       rm  *.o     gcc  -

linux下的 进程控制 以及常见的进程控制函数

进程控制: 1. 进程创建函数: fork(); 头文件: #include<sys/types.h> #include<unistd.h> 函数原型: pid_t fork(void); 函数返回值:0:表示此进程现在是子进程: -1:表示出错: 子进程ID号:(大于零的整数):表示现在此进程时父进程,接收到的ID号是子进程的ID号: 2.fork()返回-1(也就是进程创建出错的原因) 1.系统中拥有了太多的进程:超过了系统的限制:(系统级) 2.该用户有了太多的进程,超过了C

linux与Windows进程控制

进程管理控制 这里实现的是一个自定义timer用于统计子进程运行的时间.使用方式主要是 timer [-t seconds] command arguments 例如要统计ls的运行时间可以直接输入timer ls,其后的arguments是指所要运行的程序的参数.如:timer ls -al.如果要指定程序运行多少时间,如5秒钟,可以输入timer -t 5 ls -al.需要注意的是,该程序对输入没有做异常检测,所以要确保程序输入正确. Linux 程序思路 获取时间 时间获取函数使用get

linux学习笔记——进程的查看和管理、systemctl命令

###########################################################################第七单元##########################################################################1.什么是进程.线程进程是一个具有独立功能的程序关于某个数据集合的一次运动活动,进程也就是系统正在做的事情线程是进程作为分配资源的基本单位. 2.进程状态运行休眠停止继续结束僵尸进程(已经结束了

Linux学习笔记&mdash;&mdash;进程查看及管理

Linux进程查看和管理工具有很多 pstree命令:以树形方式显示进程 ps [OPTION]... 常用组合:aux u: 以用户为中心组织进程状态信息显示 a: 与终端相关的进程: x: 与终端无关的进程: 常用组合:-ef             -e: 显示所有进程              -f: 显示完整格式程序信息 常用组合:-eFH             -F: 显示完整格式的进程信息             -H: 以进程层级格式显示进程相关信息 常用组合:-eo, axo

linux c 笔记 线程控制(二)

linux 下有两种方式可以使线程终止,一种是通过调用return 从线程函数返回,第二种是通过调用函数 #includevoidpthread_exit(void *retavl); 需要注意的地方:一是,主线程中如果从main函数返回或是调用了exit函数退出主线程,则整个进程终止,此时所有的其他线程也将终止.另一种是,如果主线程调用pthread_exit函数,则仅仅是主线程消亡,进程不会结束,其他线程也不会结束,直到所有的线程都结束时,进程才结束. 线程的分离状态决定一个线程以什么样的方