了解Linux中的设备驱动程序。在线阅读Linux设备驱动程序。本书讨论了以下代码
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
// create the records
TestRecords testRecord1 = new TestRecords(){Id = 1, ResourceGroup = "SIP", ServerName = "win1234", CircuitId = 0, ChannelId = 1};
TestRecords testRecord2 = new TestRecords(){Id = 2, ResourceGroup = "SIP", ServerName = "win1234", CircuitId = 0, ChannelId = 2};
TestRecords testRecord3 = new TestRecords(){Id = 3, ResourceGroup = "TDM", ServerName = "win5678", CircuitId = 0, ChannelId = 35};
TestRecords testRecord4 = new TestRecords(){Id = 4, ResourceGroup = "TDM", ServerName = "win5678", CircuitId = 0, ChannelId = 36};
TestRecords testRecord5 = new TestRecords(){Id = 5, ResourceGroup = "SIP", ServerName = "win5678", CircuitId = 4, ChannelId = 47};
TestRecords testRecord6 = new TestRecords(){Id = 6, ResourceGroup = "TDM", ServerName = "win1234", CircuitId = 8, ChannelId = 56};
// create an empty list of TestRecords to hold the records above
List<TestRecords> listTestRecords = new List<TestRecords>();
// add records to list
listTestRecords.Add(testRecord1);
listTestRecords.Add(testRecord2);
listTestRecords.Add(testRecord3);
listTestRecords.Add(testRecord4);
listTestRecords.Add(testRecord5);
listTestRecords.Add(testRecord6);
// group the records by ServerName
var resultGrouped = listTestRecords.GroupBy(x => new{x.ServerName, x.ResourceGroup}).ToList();
// select the items you need based off of the groupings
var result = resultGrouped.Select(x => new{Server = x.Key.ServerName, ResourceGroup = x.Key.ResourceGroup, CountChannel = x.Count()}).ToList();
foreach(var item in result){
Console.WriteLine(item.Server + " " + item.ResourceGroup + " " + item.CountChannel);
}
// Result:
//win1234 SIP 2
//win5678 TDM 2
//win5678 SIP 1
// win1234 TDM 1
}
}
public class TestRecords
{
public int Id {get;set;}
public string ResourceGroup {get;set;}
public string ServerName {get;set;}
public int CircuitId {get;set;}
public int ChannelId {get;set;}
}
不要static void scull_setup_cdev(struct scull_dev *dev, int index)
{
int err, devno = MKDEV(scull_major, scull_minor + index);
cdev_init(&dev->cdev, &scull_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &scull_fops;
err = cdev_add (&dev->cdev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}
和cdev_init(&dev->cdev, &scull_fops)
做同样的事情吗?
答案 0 :(得分:0)
严格来说,它们不会做同样的事情,因为 cdev_init(&dev->cdev, &scull_fops)
不仅仅是将 scull_fops
与 cdev
实例相关联。但是,正如您通过查看 kernel source code 已经注意到的那样,传递给 cdev_init
、cdev
和 file_operations
的两个结构确实与它相关联。这就是为什么 dev->cdev.ops = &scull_fops
实际上是多余的。
但是,如果您在运行时使用 cdev_alloc
为 cdev
分配内存,那么您必须手动将 file_operations
实例与其关联(例如,通过多余的线):
struct cdev *cdev_ptr = cdev_alloc();
if (cdev_ptr != NULL)
{
cdev_ptr->ops = &scull_fops;
}
else
{
/* cdev_alloc() failed */
}
我猜这就是本书示例代码中出现冗余行背后的原因。