系统编程(4)
2017-01-10 本文已影响24人
酸菜牛肉
哲学家就餐问题:
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#define N 5
sem_t kuaizis[N];
sem_t room;
void *phi_thread_func(void *arg);
int main(int argc,char argv[])
{
pthread_t thread_ids[N];
int i = 0;
sem_init(&room,0,4);
for(i = 0;i < N;i++)
{
sem_init(&kuaizis[i], 0, 1);
}
for(i = 0;i < N;i++)
{
pthread_create(&thread_ids[i],NULL,phi_thread_func,(void *)i);
}
for(i = 0;i < N;i++)
{
pthread_join(thread_ids[i],NULL);
}
return 0;
}
void *phi_thread_func(void *arg)
{
int thread_no = (int)arg;
sem_wait(&room);
sem_wait(&kuaizis[thread_no]);
sem_wait(&kuaizis[(thread_no+1)%N]);
printf("pho NO.%d eating...\n",thread_no);
sem_post(&kuaizis[(thread_no+1)%N]);
sem_post(&kuaizis[thread_no]);
sem_post(&room);
pthread_exit(NULL);
}
进程间通信
无名管道,需要亲子进程来实现
#include <stdio.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
// int pipe(int pipefds[2]);
// 参数:
// pipefds 用于接收pipe函数创建的管道文件的读写文件描述符
// pipefds[0] 指向管道文件的读端
// pipefds[1] 指向管道文件的写端
// 返回值:成功返回0,失败,返回-1
int main(int argc, char *argv[])
{
pid_t child_pid = 0;
int pipe_fds[2] = {0};
char buf[BUFFER_SIZE] = {'\0'};
// 创建pipe
if(pipe(pipe_fds) == -1)
{
perror("pipe failed");
return 1;
}
// 数据从子进程传递给父进程
if((child_pid = fork()) == 0)
{
int n = 0;
// child process
// 1.关闭子进程中管道的读文件描述符
close(pipe_fds[0]);
while(1)
{
// 2.从标准输入文件中读入数据
n = read(STDIN_FILENO, buf, BUFFER_SIZE);
// 3.将读到的数据写入到管道中
write(pipe_fds[1], buf, n);
}
}
else if(child_pid > 0)
{
int n =0;
// parent process
// 1.在父进程中关闭管道的写文件描述符
close(pipe_fds[1]);
while(1)
{
// 2.从管道中读取数据
n = read(pipe_fds[0], buf, BUFFER_SIZE);
// 3.将从管道中读取的数据写入到标准输出文件
write(STDOUT_FILENO, buf, n);
}
}
else
{
// error
}
return 0;
}
利用有名管道产生不同窗口的本地聊天
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#define USER_NAME_MAX_LEN 100
#define MSG_MAX_LEN 500
#define FILE_NAME_MAX_LEN 100
struct msg_node
{
char src_username[USER_NAME_MAX_LEN];
char dst_username[USER_NAME_MAX_LEN];
char text[MSG_MAX_LEN];
};
int main(int argc,char *argv[])
{
if(argc != 2)
{
printf("usage:%s<username>\n",argv[0]);
return -1;
}
char filename[FILE_NAME_MAX_LEN] = {'\0'};
pid_t child_pid;
sprintf(filename,"%s.fifo",argv[1]);
if(access(filename,F_OK) != 0)
{
mkfifo(filename,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
}
if((child_pid = fork()) == 0)
{
int n = 0;
struct msg_node msg;
int fd = 0;
while(1)
{
if((fd = open(filename,O_RDONLY)) == -1)
{
perror("open failed");
return -1;
}
while((n = read(fd,&msg,sizeof(msg))) > 0)
{
printf("%s ----> %s : %s\n",msg.src_username,msg.dst_username,msg.text);
}
close(fd);
}
}
else if(child_pid > 0)
{
//char buf[MSG_MAX_LEN] = {'\0'};
struct msg_node msg;
int fd = 0;
char dst_filename[FILE_NAME_MAX_LEN] = {'\0'};
strcpy(msg.src_username,argv[1]);
while(1)
{
printf("to>");
fgets(&msg.dst_username,USER_NAME_MAX_LEN,stdin);
msg.dst_username[strlen(msg.dst_username)-1] = '\0';
printf("text>");
fgets(&msg.text,MSG_MAX_LEN,stdin);
msg.text[strlen(msg.text)-1] = '\0';
sprintf(dst_filename,"%s.fifo",msg.dst_username);
//printf("%s\n",dst_filename);
if((fd = open(dst_filename,O_WRONLY)) == -1)
{
perror("open failed");
continue;
}
//printf("*****\n");
write(fd,&msg,sizeof(msg));
close(fd);
}
}
else
{
}
remove(filename);
return 0;
}
共享内存间通信,使用信号量,效率最高
两个进程实现教师信息的传递
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <stdlib.h>
#define ARR_MAX_LEN 100
int main(int argc, char *argv[])
{
int shmid = 0;
struct teacher_node
{
int tea_id;
char tea_name[ARR_MAX_LEN];
int tea_age;
char tea_favite[ARR_MAX_LEN];
};
key_t key;
struct teacher_node teacher;
memset(&teacher, 0, sizeof(teacher));
key = ftok("/", 'j');
if((shmid = shmget(key, sizeof(teacher), IPC_CREAT | S_IRUSR | S_IWUSR)) == -1)
{
perror("shmget failed");
return -1;
}
// printf("shmid = %d\n",shmid);
teacher.tea_id = 123;
strcpy(teacher.tea_name,"xiaowang");
teacher.tea_age = 23;
strcpy(teacher.tea_favite,"basketball");
struct teacher *p = shmat(shmid, NULL, 0);
//getchar();
// printf("input teacher msg:id,name,age,favite\n");
// 2.3将输入的教师信息拷贝
memcpy(p, &teacher, sizeof(teacher));
shmdt(&teacher);
return 0;
}
进程间同步同步共享资源
// 本文件是对信号量集中只有一个信号量的操作的封装
#ifndef __SQ_SEM_H__
#define __SQ_SEM_H__
#include <sys/types.h>
// semctl函数的第四个参数类型
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
// 创建/获取信号量集
int sq_sem_get(key_t key, int semflg);
// 初始化信号量集
int sq_sem_init(int semid, int value);
// 对信号量集进行wait操作(-1)
int sq_sem_wait(int semid);
// 对信号量集进行post操作(+1)
int sq_sem_post(int semid);
// 销毁信号量集
int sq_sem_destroy(int semid);
#endif
_____
#include "sq_sem.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
// 创建/获取信号量集
int sq_sem_get(key_t key, int semflg)
{
return semget(key, 1, semflg);
}
// 初始化信号量集
int sq_sem_init(int semid, int value)
{
union semun arg;
arg.val = value;
return semctl(semid, 0, SETVAL, arg);
}
// 对信号量集进行wait操作(-1)
int sq_sem_wait(int semid)
{
struct sembuf s_op;
s_op.sem_num = 0;
s_op.sem_op = -1;
s_op.sem_flg = SEM_UNDO;
return semop(semid, &s_op, 1);
}
// 对信号量集进行post操作(+1)
int sq_sem_post(int semid)
{
struct sembuf s_op;
s_op.sem_num = 0;
s_op.sem_op = 1;
s_op.sem_flg = SEM_UNDO;
return semop(semid, &s_op, 1);
}
// 销毁信号量集
int sq_sem_destroy(int semid)
{
return semctl(semid, 0, IPC_RMID);
}
_____
// 模拟在父进程和子进程之前以共享内存的方式交换数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "sq_sem.h"
struct teacher
{
int no;
char name[50];
};
int main(int argc, char *argv[])
{
pid_t child_pid = 0;
int sem_id = 0;
int shm_id = 0;
key_t key;
// 生成唯一key值用于获取信号量集和共享内存
key = ftok("/", 'a');
// 1.1获取共享内存
if((shm_id = shmget(key, sizeof(struct teacher), IPC_CREAT | 0600)) == -1)
{
perror("shmget failed");
return 1;
}
// 1.2获取信号量集用于同步使用共享内存
if((sem_id = sq_sem_get(key, IPC_CREAT | 0666)) == -1)
{
perror("sq_sem_get failed");
return 2;
}
// 1.3初始化信号量集
sq_sem_init(sem_id, 0);
if((child_pid = fork()) == 0) // 子进程
{
// 用于存储从共享内存中获取的数据
struct teacher teach;
memset(&teach, 0, sizeof(teach));
// 子进程负责从共享内存中读入数据
// 2.1绑定共享内存
struct teacher *p = (struct teacher *)shmat(shm_id, NULL, 0);
// 2.2先wait信号量,确保共享内存中有数据可读
sq_sem_wait(sem_id);
// 2.3从共享内存中读出数据
memcpy(&teach, p, sizeof(teach));
// 2.4打印读出的数据
printf("techer : no = %d, name = %s\n",
teach.no, teach.name);
// 3.解除共享内存的绑定
shmdt(p);
// 子进程退出
exit(0);
}
else if(child_pid > 0) // 父进程
{
// 用于存储从键盘读入的教师信息
struct teacher teach;
memset(&teach, 0, sizeof(teach));
// 父进程负责从键盘读入教师信息,写入共享内存
// 2.1从键盘读入教师信息
printf("input no>");
scanf("%d", &teach.no);
printf("input name>");
scanf("%s", teach.name);
// 2.2绑定共享内存
struct teacher *p = (struct teacher *)shmat(shm_id, NULL, 0);
// 2.3将输入的教师信息拷贝
memcpy(p, &teach, sizeof(teach));
// 2.4对信号量集进行post操作
sq_sem_post(sem_id);
// 3.解除共享内存的绑定
shmdt(p);
// 防止僵尸进程
wait(NULL);
// 父进程退出
exit(0);
}
else
{
}
return 0;
}