【APUE】进程一瞥
作者:互联网
基本概念
程序:存放在磁盘文件中的可执行文件
进程:程序执行的实例(process)
Cmd: ps ,top
进程ID:每个进程都有一个非负整数标识的唯一进程ID
0是调度进程,1是init进程,(大多数UNIX系统)2是页守护进程page daemon
/*除了进程ID,进程还可以用下面的函数返回其他的标志符*/
#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
创建进程
fork()
在linux中,创建新进程的唯一方法是某个已经存在的进程调用fork()函数,新创建的进程是子进程,已存在的称为父进程。
#include <unistd.h>
pid_t fork(void);
fork()函数是一个系统调用,当父进程调用fork()时,fork()返回两个值:父进程会返回子进程的pid,这是个大于0的整数,而子进程会返回0。父进程和子进程会继续执行fork()之后的语句,子进程会继承父进程的数据空间、堆和栈的副本,但是不共享存储空间。写时复制(copy-on-write)技术:内核将(数据段、栈和堆)的权限改为只读,父进程和子进程中的任一个想要修改副本,则内核只为修改区域的那块内存制作一个副本,通常是虚拟内存中的一页page。
fork()的两种用法:
1.一个父进程复制自己,使父进程和子进程同时执行不同的代码段
2.一个父进程复制自己,要执行不同的程序
vfork()
#include <unistd.h>
pid_t vfork();
vfork()和fork()的区别:
1.vfork子进程和父进程共享数据段,fork则不共享
2.vfork的子进程比父进程先执行,在它调用exec或者exit之后,父进程才会开始执行
终止进程
进程有5种正常终止进程和3种异常终止进程的方法
正常终止:
1.在main函数中使用return
2.调用eixt函数
3.调用_exit或者_Exit函数
4.进程的最后一个线程在其启动例程中执行return语句
5.进程的最后一个线程调用pthread_exit
异常终止:
1.调用abort()
2.当进程接收到某些信号时
3.最后一个线程对“取消”请求做出响应
不管进程如何终止,最后都会执行内核装的同一段代码。这段代码会关闭进程所有的描述符,释放它的存储器
若父进程在子进程结束前终止,则子进程会成”孤儿”进程,init会成为这个进程的”养父”
一个已经终止,但是父进程并未进行善后处理的进程成为僵死进程(zombie),ps状态Z
atexit
#include <stdlib.h>
int atexit(void (*func)(void));
atexit是一个退出进程注册函数。exit执行时会先执行atexit注册的函数,且多次注册多次执行,先执行后注册的函数。
exit和_exit
区别在于exit会先执行一些清理处理(例如冲洗I/O),然后返回内核,而_exit和_Exit会直接返回内核
wait和waitpid
#include <unistd.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
wait和waitpid都是阻塞的函数,但是waitpid可以设置为非阻塞,option设置为WNOHANG
exec函数族
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,
..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
char *const envp[]);
如:execlp("/bin/echo", "echo", "hello", (char *)0)
system()
#include <stdlib.h>
int system(const char *cmdsting);
system可以在程序中执行一个命令
进程会计
进程创建和终止时会创建进程会计以及写入数据,因此一直执行的进程是没有进程会计文件的,如init进程
进程调度
进程可以通过改变nice值来修改优先级,nice值越大,优先级越低
#include <unistd.h>
#include <sys/resource.h>
int nice(int nice);
int getpriority(int which, id_t who);
int setpriority(int which, id_t who, int value);
nice值基于0~2*NZERO-1,
NZERO可以通过sysconf(_SC_NZERO)获取
nice()可以返回-1,因此,返回-1不能判定失败,需要同时查看errno是否为不为0
进程时间
#include <sys/times.h>
#include <sys/resource.h>
struct rusage {
struct timeval ru_utime; /* user CPU time used */
struct timeval ru_stime; /* system CPU time used */
long ru_maxrss; /* maximum resident set size */
long ru_ixrss; /* integral shared memory size */
long ru_idrss; /* integral unshared data size */
long ru_isrss; /* integral unshared stack size */
long ru_minflt; /* page reclaims (soft page faults) */
long ru_majflt; /* page faults (hard page faults) */
long ru_nswap; /* swaps */
long ru_inblock; /* block input operations */
long ru_oublock; /* block output operations */
long ru_msgsnd; /* IPC messages sent */
long ru_msgrcv; /* IPC messages received */
long ru_nsignals; /* signals received */
long ru_nvcsw; /* voluntary context switches */
long ru_nivcsw; /* involuntary context switches */
};
clock_t times(struct tms *buf);
int getrusage(int who, strcut rusage*rusage);
标签:ru,const,APUE,一瞥,int,long,char,进程 来源: https://blog.csdn.net/sinat_33518009/article/details/89406957