1、进程标识符
每个进程都有一个非负整型表示的唯一进程ID。
ID为0的进程通常是调度进程,常常被称为交换进程(swapper)。
ID为1通常是init进程,在自举过程结束时由内核调用。该进程文件在/etc/init
#include <unistd.h>
gid_t getegid(void); 获取有效用户ID
uid_t geteuid(void);
git_t getgid(void);
uid_t getuid(void); 获取真实用户ID
2、fork
#include <unistd.h>
pid_t fork(void); 返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1
fork函数被调用一次,但返回2次,二次返回的唯一区别是子进程返回值是0,而父进程的返回值是新子进程的进程ID。
子进程和父进程继续执行fork调用之后的指令。子进程是父进程的副本。例如,子进程获得父进程数据空间、堆和栈的副本。
父、子进程并不共享这些存储空间部分,父、子进程共享正文段。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int glob = 6;
char buf[] = "a write to stdout\n";
int main(int argc, char **argv) {
int var;
pid_t pid;
var = 88;
if(write(STDOUT_FILENO,buf,sizeof(buf)-1) != sizeof(buf)-1) {
fprintf(stdout,buf);
exit(1);
}
printf("before fork");
if((pid = fork()) <0) {
printf("fork error");
} if(pid == 0) {
glob++;
var ++;
} else {
sleep(2);
}
printf("pid = %d,glob = %d,var = %d\n",getpid(),glob,var);
exit(0);
}
|
3、wait和waitpid函数
当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件。
调用wait或waitpid进程可能发生什么情况:
a)如果其所有子进程都还在运行,则阻塞。
b)如果一个子进程已经终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回。
c)如果它没有任何子进程,则立即返回
#include<sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid,int *statloc,int options);
返回值:成功返回进程ID,或出错则返回-1
两个函数的区别:
a)在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞。
b)waitpid并不等待在其调用之后的第一个终止子进程,它有若干个选项,可以控制它所等待的进程。
这二个函数的参数statloc是一个整形指针,如果statloc不是一个空指针,则终止进程的终止状态就存放在它所指向的单元内。如果不关心终止状态,则可以
将该参数指定为空指针。
检查wait和waitpid所返回的终止状态的宏
WIFEXITED(status)
WIFSIGNALED(status)
WIFSTOPPED(status)
WIFCONTINUED(status)
打印进程终止状态
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
void pr_exit(int status) {
if (WIFEXITED(status)) {
printf("normal termination,exit status %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("abnormal termination,signal number = %d%s\n", WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? "(core file generated)" : "");
#else
"");
#endif
} else if(WIFSTOPPED(status)) {
printf("child stopped,signal nuber=%d\n",WSTOPSIG(status));
}
}
int main(int argc, char **argv) {
pid_t pid;
int status;
if((pid = fork()) <0) {
printf("fork error");
} else if(pid == 0) {
exit(7);
}
if(wait(&status) != pid) {
printf("wait");
}
pr_exit(status);
exit(0);
}
|
如果一个进程有几个子进程,那么只要一个子进程终止,wait就返回。
waitpid函数返回终止子进程的进程ID,并将该子进程的终止状态存放在由statloc指向的存储单元中。
pid==-1 等待任一子进程,就这一方面而言,waitpid与wait等效。
pid > 0 等待其进程ID与pid相等的子进程。
pid == 0 等待其组ID等于调用进程组ID的任一子进程。
pid < -1 等待其组ID等于pid绝对值的任一子进程。
常量 | 说明 |
WCONTINUED
WHOHANG
WUNTTRACED
|
若实现支持作业控制,那么由pid指定的任一子进程在暂停后已经继续,但其状态尚未报告,则返回其状态
若由pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时其返回0
若某实现支持作业控制,而由pid指定的任一子进程处理于暂停状态,并且其状态自暂停以来还未报告过,则返回
其状态
|
waitpid函数区别于wait
a)waitpid可等待一个特定的进程,而wait则返回任一终止子进程的状态
b)waitpid提供了一个wait的非阻塞版本
c)waitpid支持作业控制
4、waitid
5、wait3 wait4
6、竞争条件
当多个进程都企图对共享数据进行某种处理,而最后的结果又取决于进程运行的顺序时,则我们认为这发生了竟争条件(race condition)
7、exec函数
当进程调用exec函数时,该 进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行。
因为调用exec并不创建新进程,所以前后进程的进程ID并未改变。
exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈段。
用fork可以创建新进程,用exec可以执行新程序。exit函数和二个wait函数处理终止和等待终止。这些是我们需要的基本的进程控制原语
#include <unistd.h>
execl
execv
execle
execve
execlp
execvp
返回值 :若出错则返回-1,若成功则不返回值
|
8、更改用户ID和组ID
在UNIX系统中,特权是基于用户和组ID的。
当程序需要增加特权,或需要访问当前并不允许访问的资源时,我们需要更换自己的用户ID或组ID,使得新ID具有合适的特权或访问权限。
在设计应用程序时,我们总是试图使用最小特权模型。
#include <unistd.h>
setuid
setgid
|
9、system
#include <stdlib.h>
int system(const char *cmdstring);
|
10、用户标识
#include <unistd.h>
char *getlogin(void);
找到运行该程序的用户登录名:可以调用 getpwuid(getuid())
getpwnam 在口令文件中查找用户的相应记录,确定其登录shell
相关推荐
笔记_UNIX环境网络编程卷二进程间通信_中文第二版
### UNIX环境高级编程知识点 ...这些知识点涵盖了UNIX系统的各个方面,从基础的文件操作到高级的进程管理和文件I/O,以及标准实现和兼容性问题,为读者提供了一个全面理解UNIX环境高级编程的基础。
### UNIX高级编程知识点详解 #### 一、课程体系与学习目标概述 - **语言**: 本课程主要聚焦于两种主流的编程语言:C 和 C++。 - **算法**: 学习经典算法及其优化方法,提高解决复杂问题的能力。 - **数据结构**: ...
这些笔记可能包括安装必要的编译工具、配置环境变量、解决依赖问题以及实际编程示例等步骤,确保读者能够顺利地在实践中学习Unix编程的精髓。通过实践,你可以掌握Unix系统下的程序设计和调试技巧,这对于任何Unix或...
- **示例代码分析**:书中提供了大量的实际编程示例,覆盖各种UNIX编程场景,帮助读者理解和应用所学知识。 - **调试与故障排查**:教授如何使用调试工具和技巧,高效定位和解决编程过程中遇到的问题。 #### 5. ...
UNIX 网络编程读书笔记 ...本篇读书笔记涵盖了 UNIX 网络编程的基础知识、并发服务器设计思想、TCP/IP 协议、Socket 编程、高级知识点和网络服务器设计等多个方面,对于学习 UNIX 网络编程的读者非常有价值。
- **Unix手册页**:介绍如何使用`man`命令查询Unix/Linux系统中的命令、函数等的文档,是学习Unix编程的重要资料来源。 - **系统调用与库函数**:系统调用是应用程序与操作系统内核之间的接口,库函数则是对系统调用...
它为开发者提供了丰富的命令行工具和强大的编程环境,其中C语言是UNIX系统的核心编程语言。 C语言在UNIX系统中的地位至关重要,因为UNIX最初的许多核心组件就是用C语言编写的。C语言具有简洁、高效、灵活的特点,...
《高级Linux环境编程》或称为APUE(Advanced Programming in the UNIX ...这本书不仅涵盖了UNIX编程的核心概念,还包括了许多实用的编程技巧和解决方案,是一本非常适合在Linux环境下从事系统编程学习的参考书籍。
通过以上内容,我们可以了解到Unix系统编程涉及到多个方面的知识,从操作系统的基本概念到具体的文件操作、进程管理等高级主题。掌握这些知识点对于深入理解Unix系统的工作原理以及编写高质量的应用程序至关重要。
通过阅读《LINUX与UNIX SHELL编程指南》,读者不仅可以掌握Shell编程的基本技能,还能了解到一些高级特性,如数组、子shell、进程控制等。结合书中提供的实例,读者可以逐步提升自己的Shell编程能力,从而在Linux和...
这两者的编程接口有很高的相似性,因此学习Unix编程对理解Linux编程也非常有帮助。 本书可能包含以下内容: 1. **shell编程**:讲解Bash shell和其他Unix shell的基本语法,包括命令行参数、环境变量、重定向、...
8. **库函数与系统调用**:C语言是UNIX编程的主要语言,系统调用(如上述的`open()`、`write()`等)是直接与内核交互的接口,而库函数(如`stdio.h`中的`printf()`)则提供更友好的编程体验。 9. **网络编程**:...
Linux与Unix Shell编程指南读书笔记提供了深入理解和熟练掌握Shell脚本编写技巧的宝贵资源。Shell是Linux和Unix操作系统中的命令解释器,它不仅用于交互式地执行命令,还能编写自动化任务的脚本,极大地提高了系统...