fork()函数测试

测试代码1:

# include <stdio.h>
# include <error.h>
# include <sys/types.h>
# include <string.h>
int main(int argc, char *argv[]){
	char s[] = "hello\n";
	write(1, s, strlen(s));
	printf("world\n");
	pid_t pid;
	if((pid = fork()) < 0) perror("fork error");
	else if(pid == 0) printf("i am son %d %d\n",getpid(), getppid());
	else printf("i am father %d %d %d\n",getpid(), getppid(), pid);
	return 0;
}

$ gcc unix.c -o unix

$ ./unix
hello
world
i am father 4220 2991 4221
i am son 4221 4220

 $ ./unix 1>tmp.txt

$ cat tmp.txt
hello
world
i am father 4237 2991 4238
world
i am son 4238 4237

 第一次运行结果hello world各输出一次。

第二次运行结果world输出了2次,原因是将输出重定向到文件,由于write是非缓存IO,只输出一次;而printf是标准IO,如果输出到终端设备是行缓冲的,也就是输出一行就会就会冲洗缓冲区,而输出到文件就变成全缓冲,即填满缓冲区才冲洗。fork函数之后子进程复制父进程的数据空间、堆栈,包括缓冲区的未冲洗的数据,因此world还会再输出一次到文件。另外一个问题就是文件共享问题,子进程是将父进程的文件描述符也复制一份的,也就意味着两者的进程表项的fd表共享一个文件表项,进而共享一个文件偏移量,因此两个进程写数据到文件的时候才不会互相覆盖。

测试代码2:

//unix2.c
# include <stdio.h>
int main(int argc, int *argv[]){
	printf("I am the new. My paras are \n");
	for(int i=0; i<argc; ++i) printf("%s\n",argv[i]);
	extern char **environ;
	for(char **ptr = environ; *ptr!=0; ++ptr){
		printf("%s\n",*ptr);
	}
	return 0;
}

$ gcc unix2.c -o unix2

# include <stdio.h>
//unix.c
# include <error.h>
# include <sys/types.h>
# include <string.h>
char *env_init[] ={"USER=KK", "PATH=/etc", NULL};
int main(int argc, char *argv[]){
	
	pid_t pid;
	if((pid = fork()) < 0) perror("fork error");
	else if(pid == 0){
		if(execle("/home/junior/unixt/unix2", "my arg1", "myarg2", (char *)0, env_init) < 0)
			perror("exec error");
	}
	if(waitpid(pid, NULL, 0) < 0) perror("waitpid error");
	if((pid = fork()) < 0) perror("fork error");
        else if(pid == 0){
                if(execlp("./unix2", "my arg1", "myarg2", (char *)0) < 0)
                        perror("exec error");
        }
	return 0;
}

 $ gcc unix.c -o unix

$ ./unix

I am the new. My paras are
my arg1
myarg2
USER=KK
PATH=/etc
I am the new. My paras are
my arg1
myarg2
XDG_VTNR=7
MANPATH=/home/junior/gnuplot/share/man/man1:
XDG_SESSION_ID=c2
XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/junior
CLUTTER_IM_MODULE=xim
SESSION=ubuntu
GPG_AGENT_INFO=/home/junior/.gnupg/S.gpg-agent:0:1
TERM=xterm-256color
VTE_VERSION=4205
XDG_MENU_PREFIX=gnome-
SHELL=/bin/bash
QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1

...

代码在fork之后调用exec函数将子进程替换成其他程序,这里用到execle和execlp,l代表参数以list的形式传入,以NULL结束参数;e表示定义新的环境表,p表示复制父进程的环境表,environ指针是用来查看当前进程的环境表的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值