尽管Linux系统内核对象在实现和结构上与Windows有很大的不同。但Linux系统调用提供了和Windows的API相似的对内核对象操作的接口。在进程控制,线程管理,调度优先级,同步以及IPC的实现都存在着映射关系。以下一一列进程控制方面的映射。
创建进程
Windows API声明
+-Windows API声明_-----------------------------------------------------------------------
| // 创建一个新进程
| // 执行参数lpApplicationName指定的程序,或者lpCommandLine指定的命令。
| // FALSE(0)表示失败;TRUE(非0)表示成功。
| BOOL CreateProcess(
| LPCTSTR lpApplicationName, //名称
| LPTSTR lpCommandLine, //命令字符串
| LPSECURITY_ATTRIBUTES lpProcessAttributes,//
| LPSECURITY_ATTRIBUTES lpThreadAttributes, //
| BOOL bInheritHandles, //指示子进程是否继承父进程的句柄
| DWORD dwCreationFlags,
| LPVOID lpEnviroment, //附加环境表
| LPCSTR lpCurrentDirectory, //执行目录
| LPSTARTUPINFO lpStartupInfo,
| LPPROCESS_INFORMATION lpProcessInformation
| )
+---------------------------------------------------------------------------------------+
Linux的进程模型是基于进程复制的(用户空间的所有进程都是init进程直接或间接复制而来的)。fork完成进程复制创建新的进程,而exec则替换堆、栈、数据和正文段,运行新的程序。
Linux系统调用原型
+----------------------------------------------------------------------------------------
| // #include <unistd.h>
| // 创建一个新进程
| // 子进程获取父进程数据空间、堆、栈等的副本。
| // 在父进程中返回子进程的进程ID,在子进程中返回0,小于0则失败。
| pid_t fork(void)
+---------------------------------------------------------------------------------------+
| // #include <unistd.h>
| // 执行新程序完全替换原进程程序。
| // 进程ID不变,正文段、数据、堆栈会被替换。
| // 用户ID,目录,终端,会话,不会改变。
| // execl execle execlp执行程序的参数为字符串指针列表。以为0的字符串指针结束。
| // execv execve execvp执行程序的参数为指向字符串指针数组的指针。
| // execve execle 参数中传递指向环境变量的字符串指针数组的指针。改变环境变量。
| // execvp execlp 表示在PATH中寻找参数filename。相对应pathname为执行程序的路径。
| // 执行程序的参数argv[0],或者arg0总是执行程序的名称。
| int execl(const char *pathname, const char *arg0, ..../* (char *)0 */);
| int execv(const char *pathname, char *const argv[]);
| int execle(const char *pathname, const char *arg0, .../* (char *)0 ,
| char *const envp[] */);
| int execve(const char *pathname, char *const argv[], char *const envp[]);
| int execlp(const char *filename, const char *arg0, .../* (char *)0 */);
| int execvp(const char *filename, char *const argv[]);
+---------------------------------------------------------------------------------------+
进程正常终止
Windows API声明
+----------------------------------------------------------------------------------------
| VOID ExitProcess(
| UNIT uExitCode //所有线程的终止码
| )
+---------------------------------------------------------------------------------------+
Linux下正常终止可以是: 1.调用exit清理后(调用终止注册函数)终止 2.调用用_exit或_Exit,直接内核终止。 3.最后一个线程返回 4.最后一个线程调用pthread_exit
Linux系统调用原型
+----------------------------------------------------------------------------------------
| // <stdlib.h>
| // 终止并返回status所代表的状态。
| // exit首先处理atexit注册的终止函数。清理关闭流
| // exit最终调用_exit或_Exit
| void exit();
| void exit(int status);
+---------------------------------------------------------------------------------------+
| // 成功则返回0,出错返回非0值。
| // exit调用这些函数的顺序和注册顺序相反。
| // #include <stdlib.h>
| int atexit(void (*func)(void));
+---------------------------------------------------------------------------------------+
| // #include <stdlib.h>
| // _exit和_Exit立即进入内核,不进行清理工作
| void _Exit(int status);
| //<unistd.h>
| void _exit(int status);
+---------------------------------------------------------------------------------------+
进程异常终止
Windows API声明
+----------------------------------------------------------------------------------------
| // 结束一个进程。
| // FALSE(0)表示失败,TRUE(非0)表示成功。
| BOOL TerminateProcess(
| HANDLE hProcess, // 进程句柄
| UINT uExitCode // 退出码
| );
+---------------------------------------------------------------------------------------+
Linux下的异常终止方式可以是: 1.调用abort 2.接收处理信号后终止 3.最后一个线程对取消請求做出响应
Linux 系统调用原型
+----------------------------------------------------------------------------------------
| // #include <signal.h>
| // 将信号发给进程或者进程组。
| // signo等于SIGKILL则强制终止进程。
| // 可发送其它信号,让接收进程,捕捉处理,然后终止。如(SIGTERM)
| // pid > 0 发送到相应进程,pid = 0 发送到进程所在组的进程。
| // pid = -1发送有权限向其发送信息的系统上进程。
| // pid < -1发送信息到进程组ID为pid绝对值的进程组上所有进程。
| // 权限需要:发送者的实际用户ID或有效ID等于接收者的实际用户ID或有效ID。
| // root用户进程可以向任何进程发送信号。
| // signo为0时,可以发送空信号,检测进程是否存在。
| int kill(pid_t pid, int signo)
+---------------------------------------------------------------------------------------+
| // #include <signal.h>
| // 注册信号的处理函数
| // 若成功返回之前对此信号的的处理函数。
| // SIG_IGN:忽略;SIG_DFL:默认;SIG_ERR:出错。
| void (*signal(int signo, void (*fun)(int)))(int)
|---------------------------------------------------------------------------------------+
| // #include <stdlib.h>
| // 将SIGABRT信号发给调用进程
| void abort(void)
+---------------------------------------------------------------------------------------+
Wait子进程
Windows API声明
+----------------------------------------------------------------------------------------
| // 如果子进行信赖于父进程,父进程必须掌握子进程的结束。
| // dwMilliseconds設定最大等待时间间隔,INFINITES无限等待,0则不等待。
| // 对象句柄可以是:
| // 控制台输入,系统事件,作业,
| // 进程,线程,信号量,互斥体,計時。
| DWORD WaitForSingleObject(
| HANDLE hHandle, //对象句柄
| DWORD dwMiliseconds //时间间隔设置
| )
| // bWaitAll可以設定,获得即返回,还是获取所有后返回。
| DWORD WaitForMultipleObjects(
| DWORD nCount, // 对旬句柄数组的长度
| CONST HANDLE *lpHandles, // 对象句柄数组
| BOOL bWaitAll, //
| DWORD dwMilliseconds // 时间间隔设置
| )
|---------------------------------------------------------------------------------------+
| // 用来获取子进程的终止状态。参数lpExitCode获取终止码。
| // TRUE(非零)代表成功,FALSE(零)代表失败。
| // 若子进程没有结束,lpExitCode返回STILL_ACTIVE。
| // 可获取的终止状态包括:
| // ExitProcess和TerminateProcess设置的状态值。
| // main或者WinMain函数的返回值。
| // 导致进程终止的异常代码。
| BOOL GetExitCodeProcess(
| HANDLE hProcess,
| LPDWORD lpExitCode
| )
+---------------------------------------------------------------------------------------+
Linux提供一系列wait函数,让父进程跟踪和获取子进程的终止状态。亦可通过多次调用Wait等待多个子进程结束。
Linux 系统调用
+----------------------------------------------------------------------------------------
| // #include <sys/wait.h>
| // statloc如果不为空的话,指向子进程终止状态的存放单元。
| // 可以使用测试宏,取终止状态或者信号编号
| // WIFEXITED(status) 若正常终止返回真,用WEXITSTATUS(status)获取终止状态。
| // WIFSIGNALED(status) 若异常终止(接收信号终止)返回真,
| // 用WTERMSIG(status)获取终止信号编号。
| pid_t wait(int *statloc);
| // WIFSTOPPED(status) 若作業控制中进程暂停,返回真。
| // 用WSTOPSIG(status)获取信号编号。
| // WIFCONTINUED(status) 作業控制中子进程由暂停继续,返回真。
|
| // 阻塞至到有一个子进程终止。返回终止子进程ID
| // 等待pid子进程终止。可以options控制为不阻塞(WNOHANG)。
| // pid==-1 等待任何一个子进程;pid > 0等待pid;
| // pid==0 等待组ID等于调用进程组ID的所有子进程
| // pid<-1等待组ID等于pid绝对值的子进程。
| pid_t waitpid(pid_t pid, int *statloc, int options);
|
| //rusage 要求获取终止进程和所有其子进程使用的系统资源。
| pid_t wait3(int *statloc, int options, struct rusage *reusage);
| pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *reusage);
+---------------------------------------------------------------------------------------+
环境变量
Windows API声明
+----------------------------------------------------------------------------------------
| // 为环境变量lpName設定值lpValue
| // 成功返回TRUE(非0),失败返回FALSE(0)
| BOOL SetEnviromentVariable(
| LPCSTR lpName, // 环境变量名
| LPCSTR lpValue // 对应的值
| );
+---------------------------------------------------------------------------------------+
Linux中提供更为灵活全面的环境变量操作函数。
Linux 系统调用原型
+----------------------------------------------------------------------------------------
| // <stdlib.h>
| // 获取指定环境变量的值
| char *getenv(const char *name);
| // 将形式为name = value的字符串放到环境表中
| int putenv(char *str);
| // 将指定变量设置为value,rewrite非0则更新已有变量;rewrite为0则不更新已有变量。
| int setenv(const char *name, const char *value, int rewrite);
| // 删除指定为name的环境变量
| int unsetenv(const char *name);
+---------------------------------------------------------------------------------------+