操作系统:fork、vfork、exec、signal、kill、umask

目录

1、fork

2、execlp、execl

3、执行 ps aux

4、孤儿进程、僵尸进程

5、s_mod 文件权限、umask 文件权限创建屏蔽字

6、vfork

7、子进程等待父进程,父先终止


1、fork

(1)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>

int main()
{
	pid_t pid;
	pid = fork();
	if(pid == 0){
		printf("child: pid = %d\n", getpid());
		//exit(88);
		return 99;              //进程推出时的返回值
	}
	else if(pid > 0){
		printf("father: pid = %d\n", getpid());

		//wait(NULL);                  //不关心子进程状态

		int status;
		waitpid(-1, &status, 0);

		if(WIFEXITED(status))                     //子进程正常返回
			printf("child %d exit normally with %d\n", pid, WEXITSTATUS(status));    
		                                          //子进程推出时的返回值
		else                                      //子进程非正常返回
			printf("child %d exit abnormally\n", pid);
	}

	return 0;
}



./test
father: pid = 6890
child: pid = 6891
child 6891 exit normally with 99

(2)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>

int main()
{
	pid_t pid;
	pid = fork();
	if(pid == 0){
		printf("child: pid = %d\n", getpid());
		sleep(10);

		printf("child %d exit\n",getpid());
		//exit(88);
		return 99;              //进程推出时的返回值
	}
	else if(pid > 0){
		printf("father: pid = %d\n", getpid());

		int status;
		waitpid(-1, &status, 0);

		if(WIFEXITED(status))       //子进程正常返回
			printf("child %d exit normally with %d\n", pid, WEXITSTATUS(status));   
                                                        //子进程推出时的返回值
		if(WIFSIGNALED(status))     //子进程非正常返回,收到信号
			printf("child %d exit by signal %d\n", pid, WTERMSIG(status));           
                                                        //kill -9 child_pid,9号信号
	}

	return 0;
}



./test
father: pid = 7251
child: pid = 7252
child 7252 exit by signal 9

// kill -9 7252       //开另一个终端,执行

kill -l  // 查看信号

2、execlp、execl

       exec 族函数执行成功不返回,直接在子进程中加载要执行的新程序。执行失败,则返回-1,执行子进程调用该函数之后的代码。

       借用了进程的壳子,加载和执行了新的程序。pid 并没有改变,并且继承了打开的文件描述符。

       WIFEXITED(status);      // 宏函数,判断子进程是否正常退出。

       WEXITESTATUS(status);       // 正常终止的退出值。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>

int main()
{
	pid_t pid;
	pid = fork();
	if(pid == 0){
		printf("child: pid = %d, father: %d\n", getpid(), getppid());
		
		//execlp("ls", "ls", "-l", NULL);             //执行其他程序,p代表环境变量。执行成功不返回,执行失败才返回。
		
		//execl("./test", "test", NULL);                //不加环境变量,直接某路径下的程序
	
		char *argv[] = {"ls", "-l", NULL};
		execvp("ls", argv);
	}
	else if(pid > 0){
		printf("father: pid = %d\n", getpid());

		int status;
		waitpid(-1, &status, 0);                  //-1等所有进程,status结束状态,0阻塞等待。只要等到一个,则返回。
		//wait(&status);                          //


		if(WIFEXITED(status))                     //子进程正常返回。宏函数
			printf("child %d exit normally\n", pid);
		else                                      //子进程非正常返回
			printf("child %d exit abnormally: %d\n", pid, WEXITSTATUS(status));
	}

	return 0;
}

3、执行 ps aux

ps ajx    // 可以打印 pid,ppid

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <fcntl.h>

int main()
{
	//打开一个文件,保存 ps aux 的输出结果
	int fd;
	fd = open("ps.out", O_WRONLY|O_CREAT|O_TRUNC, 0644);
	if(fd<0){
		perror("open ps.out error");
		exit(1);
	}

	//修改标准输出
	dup2(fd, STDOUT_FILENO);

	//执行命令 ps -aux
	execlp("ps", "ps", "aux", NULL);     //不返回
	perror("execlp error");

	//close(fd);                 // 无法关闭文件,只能在成员运行结束后隐式关闭
	
	return 0;
}

 

 

4、孤儿进程、僵尸进程

       孤儿进程:父进程先死亡,子进程的父进程变为 init 进程,这样的子进程成为孤儿进程。

       僵尸进程:子进程死亡,但是内核中还保留着子进程的pcb没有倍回收,其中记录了子进程的死亡原因。kill 命令无法清除僵尸进程。

(1)如何回收僵尸进程

       由父进程调用 wait 回收;

       设置 signal(SIGCHLD, SIG_IGN);    // 父进程忽略子进程的回收信号,由内核负责回收

       父进程正常终止,或者,杀死父进程,僵尸子进程变为孤儿进程,并立即由 init 进程回收。

(2)

 

5、s_mod 文件权限、umask 文件权限创建屏蔽字

       文件的9种权限

S_IRUSR
S_IWUSR
S_IXUSR

S_IRGRP
S_IWGRP
S_IXGRP

S_IROTH
S_IWOTH
S_IXOTH
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>

#define  RWRWRW  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
#define  RWRW    S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH

int main()
{
	pid_t pid, wpid;

	signal(SIGCHLD, SIG_IGN);   // 忽略,由内核代为回收

	pid = fork();	

	if(pid == 0){
			printf("child pid : %d\n", getpid());
			sleep(1);
			printf("child exit\n");
	}
	else if(pid > 0){
		printf("father: pid = %d\n", getpid());
		
		umask(0);           // 不屏蔽任何权限
		if(creat("file_1", RWRWRW) < 0){
			printf("create file_1 error\n");
			exit(1);
		}

		umask(RWRW);	    // 屏蔽:用户组读写、其他读写权限,再创建的文件将不具有这些权限
		if(creat("file_2", RWRWRW) < 0){
			printf("create file_2 error\n");
			exit(1);
		}
	}
	else {
		printf("fork error\n");
	}

	return 0;
}


ls -l

-rw-rw-rw-. 1 name name     0 9月  25 17:00 file_1
-rw-------. 1 name name     0 9月  25 17:00 file_2     // 文件2某些权限并没有获得

6、vfork

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>

int main()
{
	pid_t pid;
	int cnt = 0;	
	
	//signal(SIGCHLD, SIG_IGN); 

	pid = vfork();	                      // vfork
	
	if(pid == 0){
		printf("child pid : %d\n\n", getpid());
		cnt++;                         // 子进程对 cnt 进行修改
		
		//exit(1);
		_exit(1);                      // vfork必须退出,标志子进程推出,父进程之后运行。否则未知错误
	}
	else if(pid > 0){
			
		printf("father: pid = %d\n", getpid());
		printf("cnt = %d\n", cnt);     // 父进程打印 cnt
	}
	else {
		printf("fork error\n");
	}

	return 0;
}
./test7_vfork 
child pid : 16774

father: pid = 16773
cnt = 1

7、子进程等待父进程,父先终止

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>

int main()
{
	pid_t pid;	
	
	signal(SIGCHLD, SIG_IGN); 

	pid = fork();	        // vfork
	
	if(pid == 0){
		while((getppid() != 1)){            //等待父进程先执行完,由 init 进程接管
			printf("child pid : %d, wait father : %d\n", getpid(), getppid());
			sleep(1);
		}
		printf("child exit\n");
	}
	else if(pid > 0){
		printf("father: pid = %d\n", getpid());
		sleep(2);
		printf("father exit\n");
	}
	else {
		printf("fork error\n");
	}

	return 0;
}
./test8_rece 

father: pid = 16749
child pid : 16750, wait father : 16749
child pid : 16750, wait father : 16749
father exit
child exit

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值