進(jìn)程的讀寫
寫文件的進(jìn)程只能單個(gè)運(yùn)行(寫的時(shí)候禁止讀),讀文件的進(jìn)程可以同時(shí)有多個(gè)贸诚,
讀寫的互斥鎖wsem秧了,rsem
讀寫進(jìn)程的優(yōu)先性同級(jí),讀進(jìn)程有優(yōu)先權(quán)時(shí)(讀的時(shí)候拿走寫鎖)受扳,
進(jìn)程間通信方式
Pipe, fifo, shared memory, mmap, samaphone, socket, mesgq,
有名管道和無(wú)名管道
共享文件
共享內(nèi)存
消息隊(duì)列
內(nèi)存映射
socket監(jiān)聽套接字
信號(hào)量
管道
管道通信詳解
管道為單向, Pipe携龟,上級(jí)進(jìn)程創(chuàng)建,無(wú)名管道通信
pipe, pipe2 - create pipe
#include <unistd.h>
int pipe(int pipefd[2]);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Obtain O_* constant definitions */
#include <unistd.h>
int pipe2(int pipefd[2], int flags);
return -1 為失敗
管道通信函數(shù)例
// ./named-pipe-chat 發(fā)送消息
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
// 用戶名的最大長(zhǎng)度
#define USER_NAME_MAX_LEN 100
// 發(fā)送消息文本的最大長(zhǎng)度
#define MSG_MAX_LEN 500
// 文件名的最大長(zhǎng)度
#define FILE_NAME_MAX_LEN 100
// 聊天消息結(jié)構(gòu)體類型
struct msg_node
{
// 發(fā)送消息用戶名
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[])
{
// 判斷命令行參數(shù)是否滿足條件
if(argc != 2)
{
printf("usage : %s <username>\n", argv[0]);
return 1;
}
// 子進(jìn)程ID
pid_t child_pid;
// 登陸用戶的命令管道文件名
char filename[FILE_NAME_MAX_LEN] = {'\0'};
// 構(gòu)造登陸用命名的管道文件名勘高,并判定用戶是否存在
sprintf(filename, "%s.fifo", argv[1]);
if(access(filename, F_OK) != 0)//判斷用戶名文件是否存在峡蟋,存在返回0
{
mkfifo(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
}
// 創(chuàng)建子進(jìn)程
if((child_pid = fork()) == 0) // 子進(jìn)程中執(zhí)行的代碼,子進(jìn)程負(fù)責(zé)接收其他用戶發(fā)送的消息并打印顯示
{
int n = 0;
struct msg_node msg;
int fd = 0;
// 1.打開登陸用戶的管道文件相满,用于接收其他用戶發(fā)送的消息數(shù)據(jù)結(jié)構(gòu)體
if((fd = open(filename, O_RDONLY)) == -1)
{
perror("open failed");
return 1;
}
// 2.循環(huán)的從管道文件中讀入消息信息,并打印顯示
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) // 父進(jìn)程桦卒,負(fù)責(zé)從鍵盤讀入相關(guān)數(shù)據(jù)立美,寫入執(zhí)行用戶的管道文件
{
struct msg_node msg ;
int fd = 0;
// 接收用戶的管道文件名
char dst_filename[FILE_NAME_MAX_LEN] = {'\0'};
// 發(fā)送者永遠(yuǎn)為當(dāng)前登錄用戶
strcpy(msg.src_username, argv[1]);
// 1.輸入接收消息的用戶名名稱
printf("to>");
fgets(&msg.dst_username, USER_NAME_MAX_LEN, stdin);
// 1.1將用戶名末尾的'\n'替換為'\0'
msg.dst_username[strlen(msg.dst_username)-1] = '\0';
// 1.2構(gòu)造接收用戶的管道文件名
sprintf(dst_filename, "%s.fifo", msg.dst_username) ;
// 1.3打開管道文件
if((fd = open(dst_filename, O_WRONLY)) == -1)
{
perror("open failed");
return 1;
}
// 循環(huán)的發(fā)送從鍵盤讀入的數(shù)據(jù)
while(1)
{
// 2.輸入待發(fā)送的消息字符串
printf("text>");
fgets(&msg.text, MSG_MAX_LEN, stdin);
// 2.2將消息文本末尾的'\n'替換為'\0'
msg.text[strlen(msg.text)-1] = '\0';
// 3.將構(gòu)造的消息結(jié)構(gòu)體寫入管道文件
// 3.2將構(gòu)造的結(jié)構(gòu)體寫入管道文件
write(fd, &msg, sizeof(msg));
// 3.3close
}
close(fd);
}
else
{
}
// 刪除登陸用戶的管道文件
remove(filename);
return 0;
}
有名管道通信
mkfifo
mkfifo - make a FIFO special file (a named pipe)
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
return 成功返回0,失敗返回1
有名管道--寫信息
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int n = 0;
char buf[1024] = {'\0'};
int fd = 0;
// 判斷有名管道文件是否存在方灾,不存在則創(chuàng)建
if(access("test_file.fifo", F_OK) != 0 )
{
mkfifo("test_file.fifo",
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
}
// 1.打開管道文件
if((fd = open("test_file.fifo", O_WRONLY)) == -1)
{
perror("open failed");
return 1;
}
printf("waiting for input data...\n");
while(1)
{
// 2.從標(biāo)準(zhǔn)輸入文件中讀入數(shù)據(jù)
n = read(STDIN_FILENO, buf, 1024);
// 3.將讀到的數(shù)據(jù)寫入到管道文件中
write(fd, buf, n);
}
printf("writer process exit...\n");
return 0;
}
有名管道--讀取信息
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
int n = 0;
char buf[1024] = {'\0'};
int fd = 0;
// 1.打開管道文件
fd = open("test_file.fifo", O_RDONLY);
if(fd == -1)
{
perror("open failed");
return 1;
}
printf("reading for writer data...\n");
// 2.從管道文件中讀取數(shù)據(jù)
while((n = read(fd, buf, 1024)) > 0)
{
// 3.將讀到的數(shù)據(jù)寫入到標(biāo)準(zhǔn)輸出文件中
write(STDOUT_FILENO, buf, n);
}
printf("reader process exit...\n");
return 0;
}
互斥鎖建蹄,線程間通信的函數(shù)例
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
//有限資源的使用中,避免死鎖裕偿。
//哲學(xué)家吃飯問(wèn)題洞慎,有五只筷子,五個(gè)人嘿棘,每人用二只劲腿,不允許沖突。
#define N 5
sem_t kuaizis[N];
sem_t room;
void *phi_thread_func(void *arg);
int main ()
{
int i =0;
pthread_t thread_ids[N];
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("%d eating\n",thread_no);
sem_post(&kuaizis[(thread_no+1)%N]);
sem_post(&kuaizis[thread_no]);
sem_post(&room);
pthread_exit(NULL);
}