(当年年少无知,代码写的烂。勿喷呀~~~)
无名管道介绍2
一.简介
本列程是由“进程与线程”中的进程附属程序加入了一个管道来显示延时时间(并没用管道去传输数据,如果要用的话需使用select函数。有兴趣的同学可以自己完成,在实名管道中还会使用到。select函数的具体用法请参阅书名数管道一节和百度百科。)(自写)
二.重点掌握函数:
无新函数
三.要求水平
可使用内来进行进程通信。
四.由于使用了前面所用到的程序所以没有加备注。
#include <stdio.h>
#include <stddef.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#define PWM_IOCTL_SET_FREQ 1
#define PWM_IOCTL_STOP 0
#define ESC_KEY 0x1b
pthread_mutex_t mutex;
int fds[2]; // 这里的fds是文件描述符的数组,用于创建管道做准备的
typedef struct{int age;
} people;
static int fd = -1;
static void close_buzzer(void);
void open_led(int on,int led_on);
int led_ons(int leds,char i);
void delay(int times);
void reader_function(people *p_data);
void writer_function(people *p_data);
static int getch(void)
{
struct termios oldt,newt;
int ch;
if (!isatty(STDIN_FILENO)) {
fprintf(stderr, "this problem should be run at a terminal\n");
exit(1);
}
// save terminal setting
if(tcgetattr(STDIN_FILENO, &oldt) < 0) {
perror("save the terminal setting");
exit(1);
}
// set terminal as need
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) < 0) {
perror("set terminal");
exit(1);
}
ch = getchar();
// restore termial setting
if(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) < 0) {
perror("restore the termial setting");
exit(1);
}
return ch;
}
static void open_buzzer(void)
{
fd = open("/dev/pwm", 0);
if (fd < 0) {
perror("open pwm_buzzer device");
exit(1);
}
// any function exit call will stop the buzzer
atexit(close_buzzer);
}
static void close_buzzer(void)
{
if (fd >= 0) {
ioctl(fd, PWM_IOCTL_STOP);
close(fd);
fd = -1;
}
}
static void set_buzzer_freq(int freq)
{
// this IOCTL command is the key to set frequency
int ret = ioctl(fd, PWM_IOCTL_SET_FREQ, freq);
if(ret < 0) {
perror("set the frequency of the buzzer");
exit(1);
}
}
static void stop_buzzer(void)
{
int ret = ioctl(fd, PWM_IOCTL_STOP);
if(ret < 0) {
perror("stop the buzzer");
exit(1);
}
}
int main(void)
{
int shm_id;
key_t key;
people *p_map;
char* name = "/dev/shm/myshm2";
pid_t pid;
pid_t pid2;
if(pipe(fds)<0) // 创建管道1
printf("pipe create error\n");
key = ftok(name,0); //创建共享内存
if(key==-1)
perror("ftok error");
shm_id=shmget(key,4096,IPC_CREAT);
if(shm_id==-1)
{
perror("shmget error");
return;
}
p_map=(people*)shmat(shm_id,NULL,0);
//printf("text2\n");
// close(fds[0]); //这样写是错误的,因为管道只能单向传输,而且如果进 //程1在某一时刻读or写,而进程2中的写or读被关闭那样管道就会破裂。
// write(fds[1],&data,1);
//printf("text3\n%d\n",data);
pthread_mutex_init(&mutex,NULL);
pid=fork();
if(pid < 0)
{
printf("error!\n");
}
else
if(pid==0)
{
pid2=fork();
if(pid < 0)
{
printf("error!\n");
}
else
if(pid==0)
{
while(1)
{
int d_time;
pthread_mutex_lock(&mutex);
close(fds[1]); //这里是子进程,先关闭管道的写入端,然后 //在管道的读出端读出数据
read(fds[0],&d_time,2);//最后位若写0代表原(buhaoshi), //若写1,2等代表的是字节数。INT在linux中为4字节但管道最大4096=(2^10)*4
printf("Cycle time has been modified, now value is:%d.\n",d_time);
pthread_mutex_unlock(&mutex);
}
}
else
{
writer_function(p_map);
}
}
else
{
reader_function(p_map);
}
}
void writer_function(people *p_data)
{
int last;
int off;
int led_on=-1;
int f_led;
// float dl;
while(1)
{
off=1;
led_on++;
if(led_on==4)
{
led_on=0;
}
open_led(1,led_on);
for(f_led=3;f_led>0;f_led--)
{
last=led_ons(led_on,off);
open_led(0,last);
off++;
}
delay((p_data->age)*8);
}
}
void reader_function(people *p_data)
{
int freq = 1000 ;
int temp;
open_buzzer();
printf( "\nBUZZER TEST ( PWM Control )\n" );
printf( "Press +/- to increase/reduce the frequency of the BUZZER\n" ) ;
printf( "Press 'ESC' key to Exit this program\n\n" );
while(1)
{
int key;
set_buzzer_freq(freq);
pthread_mutex_lock(&mutex);
temp=((21000-freq)/10);
p_data->age=temp;
close(fds[0]);
write(fds[1],&temp,2);
pthread_mutex_unlock(&mutex);
printf( "\tFreq = %d\n", freq );
key = getch();
switch(key)
{
case '+':
if( freq < 20000 )
freq += 10;
break;
case '-':
if( freq > 11 )
freq -= 10 ;
break;
case ESC_KEY:
case EOF:
stop_buzzer();
exit(0);
default:
break;
}
}
}
void open_led(int on,int led_on)
{
int ss;
ss= open("/dev/leds0", 0);
if (ss< 0)
{
ss= open("/dev/leds", 0);
}
if (ss< 0)
{
perror("open device leds");
exit(1);
}
/*通过系统调用 ioctl 和输入的参数控制 led*/
ioctl(ss, on, led_on);
/*关闭设备句柄*/
close(ss); //delete????????
}
int led_ons(int leds,char i)
{
int a;
a=leds;
for(i;i>0;i--)
{
a++;
if(a==4)
{a=0;}
}
return a;
}
void delay(int times)
{
int i;
for(;times>0;times--)
for(i=0;i<400;i++);
}