系统相关
首页 > 系统相关> > 【APUE】进程一瞥

【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