完整版生產(chǎn)者代碼:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/file.h>
#include <string.h>
#define MAXLEN 10
#define ALPHABET 1
#define ALPHABET_START 'a'
#define COUNT_OF_ALPHABET 26
#define DIGIT 2
#define DIGIT_START '0'
#define COUNT_OF_DIGIT 10
#define SIGN_TYPE ALPHABET
const char * fifo_file = "./FIFO.txt";
char buf[MAXLEN];
int lock_set(int fd, int type){
struct flock old_lock, lock;
lock.l_whence = SEEK_SET; //加鎖區(qū)域?yàn)槲募_始處
lock.l_start = 0;//加鎖區(qū)域在文件位置的相對(duì)偏移量
lock.l_len = 0;//加鎖區(qū)域長(zhǎng)度
lock.l_type = type;//鎖的類型
lock.l_pid = -1;
fcntl(fd, F_GETLK, &lock);//寫入
if(lock.l_type != F_UNLCK){//若未解鎖
if(lock.l_type == F_RDLCK){//讀取鎖
printf("Read lock already set by %d\n", lock.l_pid);
}
else if(lock.l_type == F_WRLCK){
printf("Write lock already set by %d\n", lock.l_pid);
}
}
/*上述可能由于不是解鎖狀態(tài)l_type被設(shè)置成了相應(yīng)的鎖值下方進(jìn)行上鎖操作時(shí)要再次調(diào)用type*/
lock.l_type = type;
if((fcntl(fd, F_SETLKW, &lock)) < 0){//上鎖失敗
printf("Lock failed:type = %d\n", lock.l_type);
return -1;
}
switch(lock.l_type){
case F_RDLCK:
printf("Read lock set by %d\n", getpid());//獲取當(dāng)前進(jìn)程的ID
break;
case F_WRLCK:
printf("Write lock set by %d\n", getpid());
break;
case F_UNLCK:
printf("Release lock by %d\n", getpid());//解鎖返回1
return 1;
break;
}
return 0;//上鎖返回0
}
int product(void){
int fd;
unsigned int sign_type, sign_start, sign_count, size;
static unsigned int counter = 0;//只會(huì)執(zhí)行一次
if((fd = open(fifo_file, O_WRONLY|O_APPEND)) < 0){//只寫方式打開 ,追加模式
perror("open error");
return -1;
}
sign_type = SIGN_TYPE;//英文字符集合
switch(sign_type){
case ALPHABET:
sign_start = ALPHABEF_START;
sign_count = COUNT_OF_ALPHABET;//26
break;
case DIGIT:
sign_start = DIGIT_START;
sign_count = COUNT_OF_DIGIT;
break;
default:
return -1;
}
sprintf(buf, "%c", (sign_start + counter));//將字符寫入buf緩沖區(qū)
counter = (counter + 1) % sign_count;
lock_set(fd, F_WRLCK);//寫鎖
if((size = write(fd, buf, strlen(buf))) < 0){//打開失敗,否者寫入
perror("producer:write error");
return -1;
}
lock_set(fd, F_UNLCK);//解鎖
close(fd);
return 0;
}
int main(int argc, const char * argv[]){
int time_step = 1;//周期
int time_life = 10;//生產(chǎn)數(shù)量
close(open(fifo_file, O_REONLY|O_CREAT|O_TRUNC, 0664));//創(chuàng)建文件
if(argc > 1){
sscanf(argv[1], "%d", &time_step);//將argv[1]轉(zhuǎn)成整數(shù)存入time_step中
}
if(argc > 2){
sscanf(argv[2], "%d", &time_life);
}
while(time_life --){
if(product() < 0){
break;
}
sleep(time_step);
}
return 0;
}
流程:
原版代碼有點(diǎn)缺失和問(wèn)題,添加的代碼如下:
原版代碼缺少創(chuàng)建文件函數(shù),以及沒(méi)有對(duì)文件清空的函數(shù)
每次啟動(dòng)一輪生產(chǎn),為了方便觀察將文件上次生產(chǎn)的內(nèi)容清空:
close(open(fifo_file, O_REONLY|O_CREAT|O_TRUNC, 0664));//創(chuàng)建文件&清空
文件打開模式必須是追加模式,否則生產(chǎn)的新數(shù)據(jù)會(huì)覆蓋原有數(shù)據(jù):
if((fd = open(fifo_file, O_WRONLY|O_APPEND)) < 0)
運(yùn)行效果:
FIFO.txt文件上次運(yùn)行時(shí)殘留有數(shù)據(jù)
生產(chǎn)五個(gè)數(shù)據(jù):
文件之前生產(chǎn)信息被清除,取而代之的是新數(shù)據(jù):
完整版消費(fèi)者代碼:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/file.h>
#include <string.h>
#define MAX_FILE_SIZE 100 * 1024 * 102
const char *fifo_file = "./FIFO.txt";
const char *temp_file = "./temp";
int lock_set(int fd, int type){
struct flock old_lock, lock;
lock.l_whence = SEEK_SET; //加鎖區(qū)域?yàn)槲募_始處
lock.l_start = 0;//加鎖區(qū)域在文件位置的相對(duì)偏移量
lock.l_len = 0;//加鎖區(qū)域長(zhǎng)度
lock.l_type = type;//鎖的類型
lock.l_pid = -1;
fcntl(fd, F_GETLK, &lock);//寫入
if(lock.l_type != F_UNLCK){//若未解鎖
if(lock.l_type == F_RDLCK){//讀取鎖
printf("Read lock already set by %d\n", lock.l_pid);
}
else if(lock.l_type == F_WRLCK){
printf("Write lock already set by %d\n", lock.l_pid);
}
}
/*上述可能由于不是解鎖狀態(tài)l_type被設(shè)置成了相應(yīng)的鎖值下方進(jìn)行上鎖操作時(shí)要再次調(diào)用type*/
lock.l_type = type;
if((fcntl(fd, F_SETLKW, &lock)) < 0){//上鎖失敗
printf("Lock failed:type = %d\n", lock.l_type);
return -1;
}
switch(lock.l_type){
case F_RDLCK:
printf("Read lock set by %d\n", getpid());//獲取當(dāng)前進(jìn)程的ID
break;
case F_WRLCK:
printf("Write lock set by %d\n", getpid());
break;
case F_UNLCK:
printf("Release lock by %d\n", getpid());//解鎖返回1
return 1;
break;
}
return 0;//上鎖返回0
}
int customing(const char * myfifo, int need){
int fd;
char buf;
int counter = 0;
if((fd = open(myfifo, O_RDONLY)) < 0){//只讀
perror("FunctI/On customing error");
return -1;
}
printf("Enjoy:");
lseek(fd, SEEK_SET, 0);
while(counter < need){
while((read(fd, &buf, 1) == 1) && (counter < need)){//read期望讀取的字符數(shù)與實(shí)際所讀一樣&&....
fputc(buf, stdout);//打印到顯示屏
counter ++;
}
}
fputs("\n", stdout);
close(fd);
return 0;
}
int myfilecopy(const char * sour_file, const char * dest_file, int offset, int count, int copy_mode){
int in_file, out_file;
int counter = 0;
char buff_unit;
if((in_file = open(sour_file, O_RDONLY|O_NONBLOCK)) < 0){//非阻塞只讀
perror("FunctI/On my filecopy error int source file\n");
return -1;
}
if((out_file = open(dest_file, O_RDWR|O_CREAT|O_TRUNC|O_NONBLOCK, 0664)) < 0){//非阻塞&打開或創(chuàng)建
perror("FUNCTI/O myfilecopy error in destinatI/on file");
return -1;
}
lseek(in_file, offset, SEEK_SET);//設(shè)置指針到指定位置
while((read(in_file, &buff_unit, 1) == 1) && (counter < count)){//讀取
write(out_file, &buff_unit, 1);//寫入
counter ++;
}
close(in_file);
close(out_file);
return 0;
}
int custom(int need){
int fd;
customing(fifo_file, need);//取
if((fd = open(fifo_file, O_RDWR)) < 0){//讀寫方式打開
perror("FunctI/On myfilecopy error in source_file");
return -1;
}
lock_set(fd, F_WRLCK);//上鎖,寫入鎖
myfilecopy(fifo_file, temp_file, need, MAX_FILE_SIZE, 0);//將第一個(gè)文件內(nèi)容復(fù)制到另一個(gè)文件,偏移>
myfilecopy(temp_file, fifo_file, 0, MAX_FILE_SIZE, 0);
lock_set(fd, F_UNLCK);//解鎖
unlink(temp_file);//刪除
close(fd);
return 0;
}
int main(int argc, const char *argv[]){
int customer_capacity = 0;
if(argc > 1){
sscanf(argv[1], "%d", &customer_capacity);//消費(fèi)數(shù)目寫入
}
if(customer_capacity > 0){
custom(customer_capacity);
}
return 0;
}
流程:
這里對(duì)open函數(shù)進(jìn)行再次擴(kuò)充講解:
當(dāng)文件被一個(gè)進(jìn)程植入寫入鎖的時(shí)候,另一個(gè)進(jìn)程仍可以通過(guò)open函數(shù)獲取該文件的標(biāo)志位,但卻不能進(jìn)行read或write函數(shù)操作,因?yàn)闀?huì)受到寫入鎖的阻止
樸素的將寫入鎖是阻止其他進(jìn)程對(duì)文件的讀寫操作,而不是open操作
之前一直不理解為什么customing函數(shù)中下列語(yǔ)句不會(huì)報(bào)錯(cuò),通過(guò)用printf函數(shù)取點(diǎn)才發(fā)現(xiàn)問(wèn)題
if((fd = open(myfifo, O_RDONLY)) < 0){//只讀
perror("FunctI/On customing error");
return -1;
}
看來(lái)看課本和懂課本是天差地別的
還有一點(diǎn)注意的是:
生產(chǎn)者代碼中的:
while(time_life --){
if(product() < 0){
break;
}
sleep(time_step);
}
其中:
sleep(time_step);
這個(gè)延時(shí)語(yǔ)句作用巨大:
lock_set(fd, F_WRLCK);//上鎖,寫入鎖
myfilecopy(fifo_file, temp_file, need, MAX_FILE_SIZE, 0);//將第一個(gè)文件內(nèi)容復(fù)制到另一個(gè)文件,偏移>
myfilecopy(temp_file, fifo_file, 0, MAX_FILE_SIZE, 0);
lock_set(fd, F_UNLCK);//解鎖
其作用是為了讓消費(fèi)者中這個(gè)文件挪動(dòng)語(yǔ)句能有時(shí)間完成
同時(shí)也用于讀取生產(chǎn)出來(lái)的字符:
while((read(in_file, &buff_unit, 1) == 1) && (counter < count)){//讀取
write(out_file, &buff_unit, 1);//寫入
counter ++;
}
上述語(yǔ)句在字符未被生產(chǎn),或者文件被鎖住,會(huì)一直等待,直到解鎖或者有字符被生產(chǎn)
例如文件中生產(chǎn)abc,消費(fèi)a,所以挪位后為bc
效果:
已生產(chǎn)五個(gè)字符:
消費(fèi)四個(gè):
最后剩一個(gè):
同時(shí)進(jìn)行如下:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-725775.html
整個(gè)文件被鎖住,只出現(xiàn)在生產(chǎn)者將生產(chǎn)的字符寫入文件和文件挪動(dòng)這倆操作文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-725775.html
到了這里,關(guān)于Linux 基本語(yǔ)句_9_C語(yǔ)言_生產(chǎn)者&消費(fèi)者的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!