Java-操作系统-5
1.18 介绍一下信号量。
参考回答
在多进程环境下,为了防止多个进程同时访问一个公共资源而出现问题,需要一种方法来协调各个进程,保证它们能够合理地使用公共资源。信号量就是这样一种机制。
信号量的数据类型为结构sem_t,它本质上是一个长整型的数。函数sem_init()用来初始化一个信号量。它的原型为:
extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));
sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。
(1)函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
(2)函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。
(3)函数sem_timedwait(sem_t *sem, const struct timespec *abs_timeout) 与 sem_wait() 类似,只不过 abs_timeout 指定一个阻塞的时间上限,如果调用因不能立即执行递减而要阻塞。
(4)函数sem_destroy(sem_t *sem)用来释放信号量sem。
使用示例代码如下
//g++ semtest.cpp -o test -lpthread
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>
sem_t sem;
/*function:获取当前时间,精确到毫秒
* */
int64_t getTimeMsec()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
void* func_sem_wait(void* arg)
{
printf("set wait\n");
sem_wait(&sem);
printf("sem wait success\n");
int *running = (int*)arg;
printf("func_sem_wait running\n");
printf("%d\n", *running);
}
void* func_sem_timedwait(void* arg)
{
timespec timewait;
timewait.tv_sec = getTimeMsec() / 1000 + 2;
timewait.tv_nsec = 0;
printf("sem_timedwait\n");
int ret = sem_timedwait(&sem, &timewait);
printf("sem_timedwait,ret=%d\n", ret);
printf("func_sem_timedwait running\n");
}
void* func_sem_post(void* arg)
{
printf("func_sem_post running\n");
printf("sem post\n");
int *a = (int*)arg;
*a = 6;
sem_post(&sem);
sem_post(&sem);
}
int main()
{
sem_init(&sem, 0, 0);
pthread_t thread[3];
int a = 5;
pthread_create(&(thread[0]), NULL, func_sem_wait, &a);
printf("thread func_sem_wait\n");
pthread_create(&(thread[2]), NULL, func_sem_timedwait, &a);
printf("thread func_sem_timedwait\n");
sleep(4);
pthread_create(&(thread[1]), NULL, func_sem_post, &a);
printf("thread func_sem_post\n");
pthread_join(thread[0], NULL);
pthread_join(thread[1], NULL);
pthread_join(thread[2], NULL);
sem_destroy(&sem);
}
1.19 说说僵尸进程和孤儿进程。
参考回答
我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。 当一个 进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。
1.20 请介绍进程之间的通信方式。
参考回答
进程间通信主要有以下几种方式
管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/wait.h> int pipe_default[2]; int main() { pid_t pid; char buffer[32]; memset(buffer, 0, 32); if(pipe(pipe_default) < 0) { printf("Failed to create pipe!\n"); return 0; } if(0 == (pid = fork())) { close(pipe_default[1]); //关闭写端 sleep(2); if(read(pipe_default[0], buffer, 32) > 0) { printf("[Client] Receive data from server: %s \n", buffer); } close(pipe_default[0]); } else { close(pipe_default[0]); //关闭读端 char msg[32]="== hello world =="; if(-1 != write(pipe_default[1], msg, strlen(msg))) { printf("[Server] Send data to client: %s \n",msg); } close(pipe_default[1]); waitpid(pid, NULL, 0); } return 1; }命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
写管道:
#include <stdio.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h> int main() { int nFd = 0; int nWrLen = 0, nReadLen = 0;; char szBuff[BUFSIZ] = {0}; /* 打开当前目录下的管道文件 */ nFd = open("pipe", O_RDWR); if (-1 == nFd) { perror("Open fifo failed\n"); return 1; } while (1) { /* 从终端读取数据 */ memset(szBuff,0,BUFSIZ); nReadLen = read(STDIN_FILENO,szBuff,BUFSIZ); if(nReadLen > 0) { /* 往管道写入数据 */ nWrLen = write(nFd, szBuff, strlen(szBuff)+1); if (nWrLen > 0) { printf("write data successful: %s \n", szBuff); } else { perror("write failed:"); } } } }
读管道:
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
int main()
{
int nFd = 0;
int nReadLen = 0;;
char szBuff[BUFSIZ] = {0};
/* 打开当前目录下的管道文件 */
nFd = open("pipe", O_RDWR);
if (-1 == nFd)
{
perror("Open fifo failed\n");
return 1;
}
while (1)
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本面试宝典均来自校招面试题目大数据进行的整理
卓越教育公司福利 132人发布