UNIX环境高级编程——进程管理和通信(总结)
- 进程: 程序的一次执行过程 动态过程,进程的状态属性会发生变化
- 程序:存放在磁盘上的指令、数据的有序集合 是个文件,可直观看到
- 动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的
- 并发性:任何进程都可以同其他进程一起并发执行
- 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
- 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推。
进程通讯原因:
- 数据传输
- 资源共享
- 通知事件
- 进程控制
- 进程互斥:多个进程同时要访问一个共享资源时,同时只允许一个进程访问,直到访问结束,释放后其他进程才能访问。
- 临界资源:同一时刻只允许一个进程访问的资源,进程中访问临界资源的那段程序代码称为临界资源。
- 进程同步:一组并发的进程按一定的顺序执行,具有同步关系的一组并发进程为合作进程,合作进程间互相发送的信号称为消息或事件。
- 死锁:多个进程竞争一种资源而形成的一种僵局,若无外力作用,这些进程无法继续向前推进。解决方法:主要有预防,使进程访问资源的顺序一致。
- 交互进程
- 批处理
- 守护进程
- 运行态(正在运行和准备运行的)
- 等待(可中断等待、不可中断等待)
- 僵尸态
- 停止态
- 用户模式
- 内核模式
- 抢占式
- 非抢占式
- 先来先服务
- 短进程优先
- 高优先级进程优先
- 时间片轮转法
- fork():子进程拷贝父进程的数据段,代码段. vfork():子进程与父进程共享数据段.
- fork():父子进程的执行次序不确定。vfork():保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec,或exit之后父进程才可能被调度运行
- vfork()保证子进程先运行,在她调用exec或exit之后父进程才可能被调度运行。
- return 0
- void exit( int status )<stdlib.h>
- void _exit( int status ) <unistd.h>
- _exit( ) 直接结束进程,清除其使用的内存空间,销毁其在内核中的数据结构,不刷新缓冲区。
- exit( ) 退出时要清理缓存区
const char *path,
const char *arg,
……
);
const char *path,
char * const argv[ ]
);
const char *path,
const char *arg,
…… ,
char * const envp[ ]
);
const char *path,
char * const arg[ ],
…… ,
char * const envp[ ]
);
const char *file,
const char *arg,
……
);
const char *file,
char *const arg,
……
);
- 找不到文件或路径,errno被设置为ENOENT
- 数组argv和envp忘记用NULL结束,errno被设置为EFAULT
- 没有对应的可执行文件运行权限,errno被设置为EACCESS
int *status
);
pid_t pid,
int * status,
int options
);
- 没有子进程或子进程都退出,立即返回-1
- 没有任何子进程结束,父进程会阻塞,直到有子进程退出。哪个先结束先回收哪个
- 有子进程结束,回收返回
- 检查参数的个数
- 打开源文件、目标文件(注意打开方式和权限)
- 创建子进程
- 子进程中:关源、目标文件, 重新打开后复制后半部分
- 父进程中:复制前半部分
守护进程的特点:
- 是后台服务进程,生存期较长的进程,通常独立于控制终端,周期性的执行某种任务或等待处理某些发生的事件。
- 系统启动时开始运行,在系统关闭时终止
守护进程的创建:
- fork ()创建子进程,父进程退出。
- setsid()子进程中创建新会话
- chdir(“/”) 改变工作目录
- umask(0) 重设文件权限掩码
- close(fd)关闭文件描述符
启动:
- 在Linux系统启动时从启动脚本/etc/rc.d中启动,由作业规划进程crond启动
- 用户终端(通常是 shell)执行。
- AT&T的贝尔实验室,对Unix早期的进程间通信进行了改进和扩充,形成了“system V IPC”,其通信进程主要局限在单个计算机内
- BSD(加州大学伯克利分校的伯克利软件发布中心),跳过了该限制,形成了基于套接字(socket)的进程间通信机制
- 无名管道(pipe)
- 有名管道(fifo)
- 信号(signal)
- 共享内存(share memory)
- 消息队列(message queue)
- 信号灯(semaphore)
- 套接字(socket)
- 只能用在有血缘关系的进程之间的通信、半双工(单方向的数据)。
- 类似于文件IO的读写,只存在于内存中。
int fd[2]
//
读管道,而fd[1]固定用于
写管道。)
);
- 管道中有数据,返回读取的字节数。
- 无数据,阻塞到有数据。
- 管道中有数据,返回读取的字节数。
- 无数据,返回0,所以,read返回0意味着写端关闭了。
- 空间足,返回写入的字节数。
- 空间不足,有多少写多少,直到写完返回。
- 进程被SIGPIPE信号终止。
- 类似队列、全双工(可读可写)
- 有名管道可以使互不相关的两个进程互相通信。有名管道可以通过路径名来指出,并且在文件系统中可见
- 进程通过文件IO来操作有名管道
- 有名管道遵循先进先出规则
- 不支持如lseek() 操作
const char *filename,//要创建的管道。
mode_t mode //指定创建的管道的访问权限,一般用8进制数表示.
);
参数filename所指定的目录路径无可执行的权限
参数filename所指定的文件已存在
参数filename的路径名称太长
参数filename包含的目录不存在
文件系统的剩余空间不足
参数filename指定的文件存在于只读文件系统内
- 缺省:Linux对每种信号都规定了默认操作(signal(SIGUSR1,SIG_DFL))。
- 忽略:但SIGKILL、SIGSTOP不能被忽略,只能按默认操作去执行(signal(SIGUSER1,SIG_IGN))。
- 捕捉:按指定的操作去执行(signal(SIGUSR1,fun//fun指向用户自定义函数的指针))。
- 后台进程需要使用信号,如xinetd
- 如果两个进程没有亲缘关系,无法使用无名管道
- 如果两个通信进程之一只能使用标准输入和标准输出,则无法使用FIFO
- SIGHUP:该信号在用户终端连接(正常或非正常)结束时发出,通常是在终端的控制进程结束时,通知同一会话内的各个作业与控制终端不再关联。(终止)
- SIGINT:该信号在用户键入INTR字符(通常是Ctrl-C)时发出,终端驱动程序发送此信号并送到前台进程中的每一个进程。(终止)
- SIGQUIT:该信号和SIGINT类似,但由QUIT字符(通常是Ctrl-\)来控制。(终止)
- SIGILL:该信号在一个进程企图执行一条非法指令时(可执行文件本身出现错误,或者试图执行数据段、堆栈溢出时)发出。(终止)
- SIGFPE:该信号在发生致命的算术运算错误时发出。这里不仅包括浮点运算错误,还包括溢出及除数为0等其它所有的算术的错误。(终止)
- SIGKILL:该信号用来立即结束程序的运行,并且不能被阻塞、处理和忽略。(终止)
- SIGALRM: 该信号当一个定时器到时的时候发出。(终止)
- SIGSTOP:该信号用于暂停一个进程,且不能被阻塞、处理或忽略。(暂停进程)
- SIGTSTP:该信号用于暂停交互进程,用户可键入SUSP字符(通常是Ctrl-Z)发出这个信号。(暂停进程)
- SIGCHLD :子进程改变状态时,父进程会收到这个信号。(忽略)
- SIGABORT :该信号用于结束进程。(终止)
pid_t pid,
raise(
int sig
- 可以发送信号给进程或进程组(实际上,kill系统命令只是kill函数的一个用户接口)。
- raise函数允许进程向自己发送信号。
unsigned int seconds //指定秒数
);
- 使用简单的signal()函数
- 使用信号集函数组
int signum,
void (*handler)(int))
void (fun)(int);
//就是你指定的文件名(已经存在的文件名),一般使用当前目录'.'。
id
//id是子序号。(一般填存任意字母或者数字)
)
- P1 创建的IPC对象如何让另一进程知道ID号?ID是系统分配的。但在创建对象时可以指定key,或者可以事先约定好
- 第一个进程用key来创建IPC对象,第二个进程只需要通过key来打开IPC对象
- 创建/打开共享内存 :需要判断是否已经创建过.
- 映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问.
- 撤销共享内存映射.
- 删除共享内存对象.
调试:
key_t key,
//
int
size, //
int shmflg
:标志位,
errno=EEXIST表示已存在。
int shmid,
//
const void *shmaddr,
//
int shmflg
const void *shmaddr
//共享内存映射后的地址
);
int shmid, //要操作的共享内存标识符
int cmd,
struct shmid_ds *buf // 指定IPC_STAT/IPC_SET时用以保存/设置属性
);
- 可看成是多个FIFO的集合,消息类型.
- 消息队列随内核持续,除内核重启或人工删除。
- 消息队列对应唯一的键值
)
key_t key,
//
int flag
//消息队列的访问权限
);
int msqid, //消息队列的ID
const void *msgp, //指向消息结构msgbuf.
size_t size, //
LEN)
int flag
//IPC_NOWAIT:消息没有发送完成函数也会立即返回;0:直到发送完成函数才返回。
);
)
int msgid, //消息队列的ID
void* msgp, //接收消息的缓冲区
size_t size, //要接收的消息的字节数
long msgtype,
int flag
);
int msgqid, //消息队列的队列ID
int cmd,
struct msqid_ds *buf
);
- posix有名信号灯
- posix基于内存的信号灯(无名信号灯)
- System V信号灯(IPC对象)
- 二值信号灯:值为0或1。与互斥锁类似,资源可用时值为1,不可用时值为0。
- 计数信号灯:值在0到n之间。用来统计资源,其值代表可用资源数。
- System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。System V 信号灯由内核维护
- Posix信号灯指的是单个计数信号灯
key_t key, //和信号灯集关联的key值
int nsems, //信号灯集中包含的信号灯数目
int semflg
//信号灯集的访问权限,通常为IPC_CREAT | 0666
);
int semid, //信号灯集ID
struct sembuf *opsptr,
size_t nops //要操作的信号灯的个数
);
short sem_num; //要操作的信号灯的编号
short sem_op; //0:等待,直到信号灯的值变成0
short sem_flg; //0,IPC_NOWAIT,SEM_UNDO
int semid, //信号灯集ID
int semnum, //要修改的信号灯编号
int cmd…/*union semun arg*/
);
进程间通讯方式比较
- pipe:具有亲缘关系的进程间,单工,数据在内存中
- fifo:用于任意进程间,双工,有文件名,数据在内存
- signal:唯一的异步通信方式
- msg:常用于cs模式中, 按消息类型访问 ,可有优先级
- shm:效率最高(直接访问内存) ,需要同步、互斥机制
- sem:配合共享内存使用,用以实现同步和互斥
UNIX环境高级编程——进程管理和通信(总结)的更多相关文章
- UNIX环境高级编程——进程基本概述
一.什么是进程 从用户的角度来看进程是程序的一次执行过程.从操作系统的核心来看,进程是操作系统分配的内存.CPU时间片等资源的基本单位.进程是资源分配的最小单位.每一个进程都有自己独立的地址空间与执行 ...
- UNIX环境高级编程——进程控制
一.进程标识符 ID为0的进程是调度进程,常常被称为交换进程.该进程是内核的一部分,它并不执行任何磁盘上的程序,因此也被称为系统进程.进程ID 1通常是init进程,在自举过程结束时由内核调用.ini ...
- Unix环境高级编程—进程控制(二)
一.函数wait和waitpid 今天我们继续通过昨天那个死爹死儿子的故事来讲(便于记忆),现在看看wait和waitpid函数. #include<sys/wait.h> pid_t w ...
- UNIX环境高级编程——进程关系
一.终端的概念 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal),控制终端是保存在PCB中的信息,而我们 ...
- UNIX环境高级编程——进程环境
一.main函数 C程序总是从main函数开始.当内核执行C程序时,在调用main前先调用一个特殊的启动例程.可执行程序文件将此启动例程指定为程序的起始地址--这是由连接编译器设置的,而连接编译器则由 ...
- Unix环境高级编程—进程关系
终端登录 网络登录 进程组 getpgrp(void) setpgid(pid_t pid, pid_) 会话: 是一个或多个进程组的集合,通常由shell的管道将几个进程编成一组. setsid(v ...
- unix环境高级编程----进程控制wait()
一.wait()函数 当一个进程中调用wait()函数的时候 (1)假设其全部的子程序都还在执行,则堵塞 (2)假设一个子进程已终止.则等待父进程获取其终止状态. (3)假设没有子进程,则返回错误. ...
- Unix环境高级编程—进程控制(三)
一.解释器文件 解释器文件属于文本文件,起始行形式为: #! pathname[optional-argument] 我们创建一个只有一行的文件如下: #!/home/webber/test/echo ...
- UNIX环境高级编程——进程间通讯方法整理
一.无名管道pipe #include <unistd.h> int pipe(int fd [2]) 二.fifo #include <sys/stat.h> int mkf ...
随机推荐
- Eclipse 代码提示不显示的问题
在备份Android SDK和Eclipse的时候出了问题,然后只能重新下载,SDK下得我都要吐血了,超慢.然后,我发现Eclipse有了新版本的,于是就下载了个新版的,结果出了问题了.所有的Andr ...
- python 面试相关
python单例模式: Python真的需要单例模式吗?我指像其他编程语言中的单例模式. 答案是:不需要! 因为,Python有模块(module),最pythonic的单例典范.模块在在一个应用程 ...
- SQLserver查询数据类型为ntext是空或NULL值的方法
--为空的值text ntext select * from lf_newsNg_utf where datalength(newsContentE)=0 or datalength(newsCont ...
- HYSBZ 2301
/*** 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数 **/ #include <iost ...
- Sort list by merge sort
使用归并排序对链表进行排序 O(nlgn) 的时间效率 /** * Definition for singly-linked list. * struct ListNode { * int val; ...
- git 代理设置
git 代理设置: git config --global http.proxy http://proxy.com:8080git config --global https.proxy http:/ ...
- js 选择器
a>b 获取a下面的直接子元素
- Logback相关知识汇总
例如:%-4relative 表示,将输出从程序启动到创建日志记录的时间 进行左对齐 且最小宽度为4格式修饰符,与转换符共同使用:可选的格式修饰符位于“%”和转换符之间.第一个可选修饰符是左对齐 标志 ...
- 质因数分解的rho以及miller-rabin
一.前言 质因数分解,是一个在算法竞赛里老生常谈的经典问题.我们在解决许多问题的时候需要用到质因数分解来辅助运算,而且质因数分解牵扯到许许多多经典高效的算法,例如miller-rabin判断素数算法, ...
- Block动画 和 Spring动画
Block动画: @interface BlockViewController () @property (weak, nonatomic) IBOutlet UIView *playView; @e ...