[APUE] 第12张习题解答

1 在linux系统中运行12-7中的程序,但把结果重定向到文件中,解释结果。

下面是12-7的代码:

#include <stdio.h>
#include <pthread.h>

pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;

void prepare()
{
	printf("preparing locks\n");
	pthread_mutex_lock(&lock1);
	pthread_mutex_lock(&lock2);
}

void parent()
{
	printf("parent unlocking locks\n");
	pthread_mutex_unlock(&lock1);
	pthread_mutex_unlock(&lock2);
}

void child()
{
	printf("child unlocking locks\n");
	pthread_mutex_unlock(&lock1);
	pthread_mutex_unlock(&lock2);
}

void *thr_fn(void *arg)
{
	printf("thread started\n");
	pause();
	return 0;
}

int main(int argc, char const *argv[])
{
	int err;
	pid_t pid;
	pthread_t tid;

	if((err = pthread_atfork(prepare, parent, child)) != 0) {
		printf("can't install fork handlers\n");
	}
	if((err = pthread_create(&tid, NULL, thr_fn, 0)) != 0) {
		printf("can't create thread\n");
	}
	sleep(2);
	printf("parent about to fork\n");
	if((pid = fork()) < 0) {
		printf("fork failed\n");
	}
	else if(pid == 0) {
		printf("child returned from fork\n");
	}
	else {
		printf("parent returned from fork\n");
	}

	return 0;
}

运行时将结果重定向到文件,结果是:

thread started
parent about to fork
preparing locks
parent unlocking locks
parent returned from fork
thread started
parent about to fork
preparing locks
child unlocking locks
child returned from fork

部分结果出现了两次,这是因为缓冲区的缘故。如果输出到终端,由于终端是行缓冲的,因此,输出一行就会直接输出到终端,但是,文件是全缓冲的,因此,只有当缓冲区满或者进程结束时,缓冲区中的内容才会输出到文件中。在fork()之前,创建了线程,由于线程共享缓冲区,线程的printf也会输出到当前进程的缓冲区,因此,在fork()之前,缓冲区中的内容有:

thread started
parent about to fork

然后,调用fork(),首先会调用prepare(),由于还是在父进程中,因此,缓冲区中的内容变成了:

thread started
parent about to fork
preparing locks

接着创建子进程,然后,会调用parent(),由于parent()会修改父进程的东西,因此,在调用parent()之前,会进行写时拷贝,拷贝缓冲区到子进程中,那么,此时父子进程缓冲区都是:

thread started
parent about to fork
preparing locks

然后,在父进程地址空间中调用parent(),返回到父进程,在子进程地址空间中调用child(),返回到子进程,父子进程分别执行之后缓冲区分别是:
//父进程的缓冲区中的内容
thread started
parent about to fork
preparing locks
parent unlocking locks
parent returned from fork

//子进程的缓冲区中的内容
thread started
parent about to fork
preparing locks
child unlocking locks
child returned from fork

等两个进程结束后就会输出到文件了,结果如开始所示。

从这个结果也可以看出,fork()产生一个进程后,确实返回两次,先返回到父进程,再返回到子进程。


其它题目现在看不太懂,待补充。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
习题 9.2: 编写一个程序,创建一个共享内存区,然后将一个文件映射到该共享区中。编写两个程序,一个程序将数据写到共享区中,另一个程序读取共享区中的数据,并将结果写到标准输出。使用信号量进行同步。 解答: 以下是一个简单的实现: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/shm.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <semaphore.h> #define SHM_SIZE 1024 // 共享内存区大小 #define SEM_NAME "/mysem" // 信号量名称 int main(int argc, char *argv[]) { int shm_fd; void *shm_ptr; sem_t *sem_ptr; int value = 0; // 创建共享内存区 shm_fd = shm_open("myshm", O_CREAT | O_RDWR, 0666); ftruncate(shm_fd, SHM_SIZE); // 映射共享内存区 shm_ptr = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); // 创建信号量 sem_ptr = sem_open(SEM_NAME, O_CREAT, 0666, 1); // 写入数据 sem_wait(sem_ptr); // 申请信号量 sprintf(shm_ptr, "%s", "Hello, world!"); sem_post(sem_ptr); // 释放信号量 // 读取数据 sem_wait(sem_ptr); // 申请信号量 printf("%s\n", (char*)shm_ptr); sem_post(sem_ptr); // 释放信号量 // 销毁信号量 sem_close(sem_ptr); sem_unlink(SEM_NAME); // 解除共享内存区映射 munmap(shm_ptr, SHM_SIZE); // 销毁共享内存区 shm_unlink("myshm"); return 0; } ``` 在这个程序中,我们使用 `shm_open` 和 `ftruncate` 函数创建了一个大小为 `SHM_SIZE` 的共享内存区,并使用 `mmap` 函数将其映射到进程的地址空间中。然后,我们使用 `sem_open` 函数创建了一个信号量,并在写入数据和读取数据的过程中使用 `sem_wait` 和 `sem_post` 函数进行同步。最后,我们使用 `munmap` 函数解除了共享内存区的映射,并使用 `shm_unlink` 函数销毁了共享内存区。 编写第二个程序时,只需要将写入数据和读取数据的顺序颠倒即可。同时,需要使用相同的共享内存区和信号量名称。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值