進程的讀寫
寫文件的進程只能單個運行(寫的時候禁止讀),讀文件的進程可以同時有多個,
讀寫的互斥鎖wsem,rsem
讀寫進程的優先性同級,讀進程有優先權時(讀的時候拿走寫鎖),
進程間通信方式
Pipe, fifo, shared memory, mmap, samaphone, socket, mesgq,
有名管道和無名管道
共享文件
共享內存
消息隊列
內存映射
socket監聽套接字
信號量
管道
管道通信詳解
管道為單向, Pipe,上級進程創建,無名管道通信
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 為失敗
管道通信函數例
// ./named-pipe-chat 發送消息
#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;
}
// 子進程ID
pid_t child_pid;
// 登陸用戶的命令管道文件名
char filename[FILE_NAME_MAX_LEN] = {'\0'};
// 構造登陸用命名的管道文件名,并判定用戶是否存在
sprintf(filename, "%s.fifo", argv[1]);
if(access(filename, F_OK) != 0)//判斷用戶名文件是否存在,存在返回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;
// 1.打開登陸用戶的管道文件,用于接收其他用戶發送的消息數據結構體
if((fd = open(filename, O_RDONLY)) == -1)
{
perror("open failed");
return 1;
}
// 2.循環的從管道文件中讀入消息信息,并打印顯示
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) // 父進程,負責從鍵盤讀入相關數據,寫入執行用戶的管道文件
{
struct msg_node msg ;
int fd = 0;
// 接收用戶的管道文件名
char dst_filename[FILE_NAME_MAX_LEN] = {'\0'};
// 發送者永遠為當前登錄用戶
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構造接收用戶的管道文件名
sprintf(dst_filename, "%s.fifo", msg.dst_username) ;
// 1.3打開管道文件
if((fd = open(dst_filename, O_WRONLY)) == -1)
{
perror("open failed");
return 1;
}
// 循環的發送從鍵盤讀入的數據
while(1)
{
// 2.輸入待發送的消息字符串
printf("text>");
fgets(&msg.text, MSG_MAX_LEN, stdin);
// 2.2將消息文本末尾的'\n'替換為'\0'
msg.text[strlen(msg.text)-1] = '\0';
// 3.將構造的消息結構體寫入管道文件
// 3.2將構造的結構體寫入管道文件
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;
// 判斷有名管道文件是否存在,不存在則創建
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.從標準輸入文件中讀入數據
n = read(STDIN_FILENO, buf, 1024);
// 3.將讀到的數據寫入到管道文件中
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.從管道文件中讀取數據
while((n = read(fd, buf, 1024)) > 0)
{
// 3.將讀到的數據寫入到標準輸出文件中
write(STDOUT_FILENO, buf, n);
}
printf("reader process exit...\n");
return 0;
}
互斥鎖,線程間通信的函數例
#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 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);
}