1.5.1 无名管道附属例程

(当年年少无知,代码写的烂。勿喷呀~~~)

无名管道介绍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++);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值