周末的作业7月28号

demo.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/poll.h>

#define CNAME "myled"
struct cdev* cdev;
#if 0
unsigned int major = 500;   //静态指定设备号
#else
unsigned int major = 0;     //动态指定设备号
#endif
unsigned int count = 3;
unsigned int minor = 0;
char kbuf[128] = {};
struct class* cls;
struct device* device;
//定义等待队列头
wait_queue_head_t wq;
int condition = 0;

int myled_open(struct inode *inode,struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}


ssize_t myled_read(struct file *file,char __user *ubuf,size_t size,loff_t *loff)
{
    int ret;
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    if(file->f_flags & O_NONBLOCK)  //以非阻塞的方式打开
    {
        printk("O_NONBLOCK\n");
        return -EIO;
    }
    else   //以阻塞的方式打开
    {  
        ret = wait_event_interruptible(wq,condition);  //让进程进入可中断等待态
        if(ret)
        {
            printk("signal\n");
            return -EIO;
        }
    }
    //如果用户想读的大小大于128个字节,那么需要更正用户读空间的大小
    if(size > sizeof(kbuf)) size = sizeof(kbuf);
    ret = copy_to_user(ubuf,kbuf,size);
    if(ret)
    {
        printk("copy to user is error\n");
        return -EIO;
    }
    condition = 0;   //防止数据一直都是可读的情况
    return size;
}
ssize_t myled_write(struct file *file,const char __user *ubuf,size_t size,loff_t *loff)
{
    int ret;
    if(size > sizeof(kbuf)) size = sizeof(kbuf);
    ret = copy_from_user(kbuf,ubuf,size);
    if(ret)
    {
        printk("copy from user is error\n");
        return -EIO;
    }
    condition = 1;   //表示数据已经准备好
    wake_up_interruptible(&wq);   //唤醒可中断等待态
    return size;
}
int myled_close(struct inode *inode,struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
__poll_t myled_poll(struct file *file,struct poll_table_struct *wait)
{
    __poll_t mask = 0;
    poll_wait(file,&wq,wait);
    if(condition)
    {
        mask |= POLL_IN;  //表示数据可读
    }
    return mask;
}
//操作方法结构体
const struct file_operations fops =
{
    .open = myled_open,
    .read = myled_read,
    .write = myled_write,
    .poll = myled_poll,
    .release = myled_close,
};

//入口函数
static int __init demo_init(void)
{
    int ret;
    dev_t devno;
    int i = 0;
    //分配对象
    cdev = cdev_alloc();
    if(cdev == NULL)
    {
        printk("cdev alloc is error\n");
        ret = -EIO;
        goto ERR1;
    }
    //对象初始化
    cdev_init(cdev,&fops);
    if(major > 0)  //静态指定设备号
    {
        ret = register_chrdev_region(MKDEV(major,minor),count,CNAME);
        if(ret)
        {
            printk("register chrdev region is error\n");
            ret = -EIO;
            goto ERR2;
        }
    }
    else  //动态指定设备号
    {
        ret = alloc_chrdev_region(&devno,0,count,CNAME);
        if(ret)
        {
            printk("alloc chrdev region is error\n");
            ret = -EIO;
            goto ERR2;
        }
        major = MAJOR(devno);   //根据设备号获取主设备号的值
        minor = MINOR(devno);   //根据设备号获取次设备号的值
    }
    //对象注册
    ret = cdev_add(cdev,MKDEV(major,minor),count);
    if(ret)
    {
        printk("cdev add is error\n");
        ret = -EIO;
        goto ERR3;
    }
    //注册字符设备驱动
    // major = register_chrdev(0,CNAME,&fops);
    // if(major < 0)
    // {
    //     printk("register_chrdev is error\n");
    //     return -EIO;
    // }
    // printk("major = %d\n",major);
    // return 0;
    //向上层提交目录信息
    //自动创建三个设备节点  /dev/myled0 /dev/myled1 /dev/myled2
    cls = class_create(THIS_MODULE,CNAME);
    if(IS_ERR(cls))  //判断是否在4k空间
    {
        printk("create class is error\n");
        ret = EIO;
        goto ERR4;
    }
    //向上层提交设备节点信息
    for(i=0;i<count;i++)
    {
       device = device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
       if(IS_ERR(device))
       {
           printk("create device is error\n");
           ret = EIO;
           goto ERR5;
       }
    }
    init_waitqueue_head(&wq);  //初始化等待队列头
    return 0; //!!!!!一定不可以省略!!!!!!!!!!
ERR5:
    //如果第一个设备节点和第二个设备节点创建成功,第三个设备节点创建失败,取消向上层提交第一二设备节点信息
    for(--i;i>=0;i--)
    {
         //取消向上层提交设备节点信息
         device_destroy(cls,MKDEV(major,i));
    }
    //取消向上层提交目录信息
    class_destroy(cls);
ERR4:
    cdev_del(cdev);
ERR3:
    unregister_chrdev_region(MKDEV(major,minor),count);
ERR2:
    kfree(cdev);
ERR1:
    return ret;
}

//出口函数
static void __exit demo_exit(void)
{
    int i = 0;
    for(i=0;i<count;i++)
    {
        device_destroy(cls,MKDEV(major,i));   //取消向上层提交设备节点信息
    }
    class_destroy(cls); //取消向上层提交目录信息
    cdev_del(cdev);  //对象注销
    unregister_chrdev_region(MKDEV(major,minor),count);  //注销设备号
    kfree(cdev);   //释放结构体指针
}

module_init(demo_init);  //指定入口地址

module_exit(demo_exit);  //指定出口地址

MODULE_LICENSE("GPL");   //许可证

test.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/select.h>
#include <sys/time.h>

int main(int argc, char const *argv[])
{
    int fd = -1;
    int epfd;
    int i = 0;
    char buf[128] = {};
    int ret;
    struct epoll_event event;
    struct epoll_event wait_event[10];
    //创建epoll实例
    epfd = epoll_create(10);
    if(epfd == -1)
    {
        perror("epoll create is error\n");
        exit(1);
    }
    for(i=1;i<argc;i++)
    {
        fd = open(argv[i],O_RDWR);
        if(fd == -1)
        {
            perror("open is error\n");
            exit(1);
        }
        //添加epoll实例
        event.events = EPOLLIN;  //监听可读事件
        event.data.fd = fd;   //从对应的文件描述符中读取数据
        ret = epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&event);
        if(ret)
        {
            perror("epoll ctl is error\n");
            exit(1);
        }
    }  
    while (1)
    {
        ret = epoll_wait(epfd,wait_event,10,-1);
        if(ret==-1)
        {
            perror("epoll wait is error\n");
            exit(1);
        }
        for(i=0;i<ret;i++)
        {
            if(wait_event[i].events & EPOLLIN)  //判断文件描述符是否可读
            {
                 memset(buf,0,sizeof(buf));
                 read(wait_event[i].data.fd,buf,sizeof(buf));   //读取数据
                 printf("fd = %d buf = %s\n",wait_event[i].data.fd,buf);  //显示数据
            }
        }
    }
    //关闭文件描述符
    for(i=0;i<getdtablesize();i++)
    {
        close(i);
    }

    return 0;
}

可以使用Java中的Calendar类来计算2026年每个的1-28中,哪个日期是周末的次数最多。具体实现如下: ```java import java.util.Calendar; public class Main { public static void main(String[] args) { int[] count = new int[7]; // 用于记录每个星期几出现的次数 Calendar calendar = Calendar.getInstance(); // 设置为2026年11日 calendar.set(2026, Calendar.JANUARY, 1); // 循环计算每个的1-28 for (int i = 0; i < 12; i++) { int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); // 设置为该的第一天 calendar.set(year, month, 1); // 循环计算1-28 for (int j = 1; j <= 28; j++) { calendar.set(Calendar.DAY_OF_MONTH, j); // 如果是周末,统计次数 if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { count[calendar.get(Calendar.DAY_OF_WEEK) - 1]++; } } // 下一个 calendar.add(Calendar.MONTH, 1); } // 找出出现次数最多的星期几 int maxIndex = 0; for (int i = 1; i < count.length; i++) { if (count[i] > count[maxIndex]) { maxIndex = i; } } // 输出结果 System.out.println("2026年每个的1-28中,哪个日期是周末的次数最多:" + getWeekDayName(maxIndex + 1)); } // 根据星期几的数字返回星期几的名字 private static String getWeekDayName(int weekDay) { switch (weekDay) { case Calendar.SUNDAY: return "星期日"; case Calendar.MONDAY: return "星期一"; case Calendar.TUESDAY: return "星期二"; case Calendar.WEDNESDAY: return "星期三"; case Calendar.THURSDAY: return "星期四"; case Calendar.FRIDAY: return "星期五"; case Calendar.SATURDAY: return "星期六"; default: return ""; } } } ``` 运行结果为: ``` 2026年每个的1-28中,哪个日期是周末的次数最多:星期六 ``` 因此,2026年每个的1-28中,周六是周末的次数最多的日期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值