赞
踩
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("pid:%d ppid:%d\n",getpid(),getppid());
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("uid:%d gid:%d euid:%d egid:%d\n",getuid(),getgid(),geteuid(),getegid());
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
system("ls -l");
system("clear");
return 0;
}
#include <unistd.h>
pid_t fork(void);
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { printf("父进程的进程id为:%d\n",getpid()); pid_t iRet = fork(); if(iRet < 0){ //创建出错 printf("子进程创建失败!\n"); } else if(iRet == 0){ //代表子进程 printf("子进程id:%d,父进程id:%d!\n",getpid(),getppid()); } else{ //代表父进程 printf("父进程成功,子进程id:%d\n",iRet); } return 0; }
int execl(const char *path, const char *arg, ...)
path是包括执行文件名的全路径名 arg是可执行文件的命令行参数,多个用,分割注意最后一个参数必须为NULL。//main.c
#include <stdio.h>
#include <string.h>
int main()
{
execl(“./a.out” ,”a.out” , NULL);//执行a.out文件
printf("hello");//不会执行
return 0 ;
}
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
command为可执行文件的全路径和执行参数
type可选参数为”r”或”w”,如果为”w”,则popen返回的文件流做为新进程的标准输入流,即stdin,如果为”r”,则popen返回的文件流做为新进程的标准输出流。
pclose等待新进程的结束,不是杀掉进程。
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> int main() { FILE *read_fp; char buffer[BUFSIZ + 1];//BUFSIZ是宏定义8192 int chars_read;//读取文件字符数量 memset(buffer, '\0', sizeof(buffer));//给缓冲区buf置空 read_fp = popen("ps -ax", "r");//使用读的方式读取ps -ax命令,并且给到read_fp指针 if (read_fp != NULL) { //循环读取打印 chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);//将读取的内容放入缓冲区buf while (chars_read > 0) { //如果读取的字符数量不为0 buffer[chars_read - 1] = '\0'; //将缓冲区的最后一个字符改为\0,方便打印输出 printf("Reading:-\n %s\n", buffer); chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); } pclose(read_fp); exit(EXIT_SUCCESS); } exit(EXIT_FAILURE); }
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { pid_t pid = fork(); if(pid == 0){ //判断是否为子进程,0是子进程,非0是父进程 while(1); } else{ //父进程则退出,让子进程变成孤儿进程 exit(10); } return 0; }
编译后运行,输入ps -ef 可以看到如下:
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { pid_t pid = fork(); if( pid == 0 ){ //pid为0是子进程,就正常退出 printf("我是子进程\n"); } else{ //父进程休眠 printf("我是父进程"); while(1);//让父进程一直执行 //sleep(20);//让父进程休眠 } return 0; }
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main() { pid_t pid = fork(); if( pid == 0 ){ exit(10); } else{ int cid = wait(NULL); //NULL表示等待所有进程,只想把僵尸进程消灭掉 printf("正在等待的子进程id为%d\n",cid); sleep(10); //通常要将sleep放在wait的后面,要不然也会出现僵尸进程 } }
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> void SignChildPsExit(int iSignNo) { int iExitCode; pid_t pid = waitpid(-1,NULL,0);//表示等待任何进程,并阻塞 //如果写成waitpid(-1,NULL,WNOHANG);表示不等待任何进程,不阻塞 printf("序号是%d 子进程号是%d\n",iSignNo,pid); if(WIFEXITED(iExitCode)){ //判断子进程是否正常退出 printf("子进程的退出码为:%d\n",WIFEXITED(iExitCode)); } sleep(10); } int main() { signal(SIGCHLD, SignChildPsExit); //SIGCHLD是子进程退出时给父进程发的信号,用函数捕捉他 printf("父进程id为%d\n",getpid()); pid_t iRet = fork(); if(iRet == 0) exit(3); }
进程的终止有五种方式:
前3种方式为正常的终止,后2种为非正常终止。但是无论哪种方式,进程终止时都将执行相同的关闭打开的文件,释放占用的内存等资源。只是后两种终止会导致程序有些代码不会正常的执行比如对象的析构、atexit函数的执行等。
#include <stdlib.h> //exit的头文件
#include <unistd.h> //_exit的头文件
void exit(int status);
void _exit(int status);
//exit的举例,调用exit后,缓冲区的记录可以正常输出
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Using exit...\n");
printf("This is the content in buffer");
exit(0);
}
_exit函数会直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;
//_exit的调用,会发现最后的This is the content in buffer没有打印输出,说明该函数无法输出缓冲区中的记录
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("Using exit...\n");
printf("This is the content in buffer");
_exit(0);
}
这里可以看到确实没有打印最后一行缓冲区的内容,调查到的资料显示,_exit为了让程序尽快退出。
#include<stdio.h> #include<unistd.h> #include<sys/stat.h> #include<sys/types.h> #include<stdlib.h> int main() { FILE* fp = fopen("./file1","r+"); char buf[32] = {'\0'}; fread(buf,sizeof(char),6,fp); //从文件中读取6个字符到buf中 printf("父进程读取文件内容%s\n",buf); //创建子进程,处理父进程 if(fork() == 0){ fclose(fp);//父进程中直接将文件关闭,清空文件指针 fp = NULL;//但是子进程在创建fock的时候就已经拷贝了父进程的PCB中fp的内容 } sleep(3);//给父进程关闭文件的时间 //子进程尝试使用fp指针读取接下来的文件内容 //实际上就连父进程中fp的偏移也被子进程拷贝了 if(fread(buf,sizeof(char),5,fp)==0){ printf("子进程继续读取失败\n"); exit(0); } else{ printf("子进程继续读取内容为%s\n",buf); exit(0); } return 0; }
daemon守护进程的编程规则:
int pid = fork();
if(pid>0)
exit(0);
进程组:是一个或多个进程的集合。进程组有唯一的组号GID。组内每个进程都有一个组长进程,其组长进程的ID号就是组ID号。且组ID号不会因为组长进程退出受到影响。
会话周期:会话期是一个或多个进程组的集合。通常,一个会话开始于用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。
控制终端:由于在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依赖这个控制终端。
创建守护进程的准备
for(i=0;i<MAXFILE;i++)
close(i);
(注:有时还要处理SIGCHLD信号signal(SIGCHLD, SIG_IGN);防止僵尸进程(zombie))
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> void Daemon() { const int MAXFD=64; int i=0; if(fork()!=0) //父进程退出 exit(0); setsid(); //成为新进程组组长和新会话领导,脱离控制终端 chdir("/"); //设置工作目录为根目录 umask(0); //重设文件访问权限掩码 for(;i<MAXFD;i++) //尽可能关闭所有从父进程继承来的文件 close(i); } int main() { Daemon(); //成为守护进程 while(1){ sleep(1); } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。