An example of Block device driver

Block Drivers

Global architecture

Block I/O on Linux
Block devices are storage media capable of random access. Unlike character devices, block devices can hold file system data.

The storage media contains files residing in a filesystem, such as EXT3 or Reiserfs. User applications invoke I/O system calls to access these files. The resulting filesystem operations pass through the generic Virtual File System (VFS) layer before entering the individual filesystem driver. The buffer cache speeds up filesystem access to block devices by caching disk blocks. If a block is found in the buffer cache, the time required to access the disk to read the block is saved. Data destined for each block device is lined up in a request queue. The filesystem driver populates the request queue belonging to the desired block device, whereas the block driver receives and consumes requests from the corresponding queue. In between, I/O schedulers manipulate the request queue so as to minimize disk access latencies and maximize throughput.

Linux I/O schedulers

  • Linus elevator
  • Deadline: tries to guarantee that an I/O will be served within a deadline
  • Anticipatory: tries to anticipate what could be the next accesses
  • Complete Fair Queuing: the default scheduler, tries to guarantee fairness between users of a block device
  • Noop: for non­disk based block devices

The current scheduler for a device can be get and set in

/sys/block/<dev>/queue/scheduler

Ramdisk Example

This example is based on kernel version 4.15.0-46-generic.

Register a block I/O device

#define MY_BLOCK_MAJOR           240
#define MY_BLKDEV_NAME          "sun_block"

static int my_block_init(void)
{
    int status;
    status = register_blkdev(MY_BLOCK_MAJOR, MY_BLKDEV_NAME);
    if (status < 0) {
             printk(KERN_ERR "unable to register mybdev block device\n");
             return -EBUSY;
    }
    printk("reigster a test block driver...\n");
    return 0;
}

static void my_block_exit(void)
{
    printk("exit my block driver..\n");    
    unregister_blkdev(MY_BLOCK_MAJOR, MY_BLKDEV_NAME);
}

module_init(my_block_init);
module_exit(my_block_exit);

Register a disk

struct gendisk is an abstraction of real disk, there are differences between gendisk and block_device. gendisk is defined in “include/linux/genhd.h”, which indicate this structure is mainly used by block device driver; Meanwhile, block_device is defined in “include/linux/fs.h”, which indicate block_device has a close relationship with filesystem.
在这里插入图片描述
For each partition of a block device that has already been opened, there is an instance of struct block_device . The objects for partitions are connected with the object for the complete device via bd_contains . All block_device instances contain a link to their generic disk data structure gen_disk via bd_disk . Note that while there are multiple block_device instances for a partitioned disk, one gendisk instance is sufficient.

The gendisk instance points to an array with pointers to hd_structs. Each represents one partition. If a block_device represents a partition, then it contains a pointer to the hd_struct in question — the hd_struct instances are shared between struct gendisk and struct block_device .

Additionally, generic hard disks are integrated into the kobject framework as shown in Figure 6-11. The block subsystem is represented by the kset instance block_subsystem . The kset contains a linked list on which the embedded kobject s of each gendisk instance are collected.
在这里插入图片描述
Partitions represented by struct hd_struct also contain an embedded kobject . Conceptually, partitions are subelements of a hard disk, and this is also captured in the data structures: The parent pointer of the kobject embedded in every hd_struct points to the kobject of the generic hard disk.

#define SECTOR_SIZE     512
#define MY_SECTORS      16
#define MY_HEADS        4
#define MY_CYLINDERS        1024    

#define MY_SECTOR_TOTAL (MY_SECTORS*MY_HEADS*MY_CYLINDERS)
#define MY_SIZE         (MY_SECTOR_TOTAL*SECTOR_SIZE)

static struct my_block_dev {
    spinlock_t lock;                /* For mutual exclusion */
    struct request_queue *queue;    /* The device request queue */
    struct gendisk *gd;             /* The gendisk structure */
    unsigned char * data;
} dev;

struct block_device_operations my_block_ops = {
    .owner = THIS_MODULE,
    .open = my_block_open,
    .release = my_block_release,
    .ioctl = my_block_ioctl,
};

static int create_block_device(struct my_block_dev *dev)
{
    dev->gd = alloc_disk(MY_BLOCK_MINORS);
    if (!dev->gd) {
        printk (KERN_NOTICE "alloc_disk failure\n");
        return -ENOMEM;
    }
    
    dev->gd->major = MY_BLOCK_MAJOR;
    dev->gd->first_minor = 0;
    dev->gd->fops = &my_block_ops;
    dev->gd->queue = dev->queue;
    dev->gd->private_data = dev;
    snprintf (dev->gd->disk_name, 32, "sun_block");
    set_capacity(dev->gd, MY_SECTOR_TOTAL);
    
    add_disk(dev->gd);
    return 0;
}

static int my_block_init(void)
{
	...
    dev.data = vmalloc(MY_SIZE); //molloc 8M RAM memory for this ramdisk
    memset(dev.data, 0, MY_SIZE);
    printk("data range 0x%x---0x%x, 0x%x", dev.data, dev.data+MY_SIZE, MY_SIZE);
    if(dev.data == NULL) {
             printk(KERN_ERR "unable to vmalloc\n");
             return -ENOMEM;
    }
    
    create_block_device(&dev);
    ...
}

static void delete_block_device(struct my_block_dev *dev)
{
    if (dev->gd)
        del_gendisk(dev->gd);
    if(dev->data)
        vfree(dev->data);
}

static void my_block_exit(void)
{
	...
    delete_block_device(&dev);
    ...
}

Request queues

Drivers for block devices use queues to store the block requests I/O that will be processed. A request queue is represented by the struct request_queue structure. request_queue contains a double linked list of request and their associated control information. There are 2 different ways to manipulate the queues: request version and make_request version.

The relationship between request and bio is showed below.
在这里插入图片描述
在这里插入图片描述

1. request version.
static void my_block_request(struct request_queue *q) 
{
    struct request *rq;
 
    while ((rq = blk_fetch_request(q)) != NULL) {
        __process_request(rq);
        __blk_end_request_all(rq, 0);
    }
}

static int create_block_device(struct my_block_dev *dev)
{
	/* Initialize the I/O queue */
	spin_lock_init(&dev->lock);
	dev->queue = blk_init_queue(my_block_request, &dev->lock);
	if (dev->queue == NULL)
		return -ENOMEM;
		...
}
2. make_request version

blk_queue_make_request does not alloc queue in its logic, so must use blk_alloc_queue to alloc a queue first.

static blk_qc_t my_make_request(struct request_queue *q, struct bio *bio)
{
    struct my_block_dev *pdev = bio->bi_disk->private_data;
    struct bio_vec bvec;
    sector_t sector;
    struct bvec_iter iter;
    char *pData, *pBuffer;

    sector = bio->bi_iter.bi_sector;
    if (bio_end_sector(bio) > get_capacity(bio->bi_disk))
        goto io_error;
        
    pData = pdev->data + (sector * SECTOR_SIZE);
    bio_for_each_segment(bvec, bio, iter) {
        __process_bio_vector();
        pData += bvec.bv_len;
    }

    bio_endio(bio);
    return BLK_QC_T_NONE;
io_error:
    bio_io_error(bio);
    return BLK_QC_T_NONE;
}

static int create_block_device(struct my_block_dev *dev)
{
    /* Initialize the I/O queue */
    spin_lock_init(&dev->lock);
    dev->queue = blk_alloc_queue(GFP_KERNEL);
    if (dev->queue == NULL)
        return -ENOMEM;
        
    blk_queue_make_request(dev->queue, my_make_request);
    blk_queue_logical_block_size(dev->queue, SECTOR_SIZE);
    ...
}

Once upper layer create a bio structure and use submit_bio(rw, bio) to process these bio, submit_bio would do some initialization and statistics work, then calling generic_make_request(bio) , this function would check if make_request_fn is active on this task right now(there might be recursive call of generic_make_request, thus, stacked bio would be considered), if yes, append the bio at the end of bio_list and return, if no, it will pop bio from current->bio_list, and call q->make_request_fn, if using request verison, the function is hooked with blk_queue_bio(q, bio), or, it’s user defined. blk_queue_bio would rearrange the bio in the queue, merge bios to optimize the operation, and copy data from new bio into queue via init_request_from_bio(req, bio). Then calling __blk_run_queue to process the queue, which would eventually call my_block_request.

Process the request

1. request version.
static void my_block_request(struct request_queue *q)
{
	...
	while ((rq = blk_fetch_request(q)) != NULL) {
        pdev = rq->rq_disk->private_data;

        rq_for_each_segment(bvec, rq, iter) {
            start = iter.iter.bi_sector;
            pData = pdev->data + start * SECTOR_SIZE;
            pBuffer = kmap(bvec.bv_page) + bvec.bv_offset;
            switch(rq_data_dir(rq))
            {
                case READ:
                    memcpy(pBuffer, pData, bvec.bv_len);
                    flush_dcache_page(bvec.bv_page);
                    break;
                case WRITE:
                    flush_dcache_page(bvec.bv_page);
                    memcpy(pData, pBuffer, bvec.bv_len);
                    break;
                default:
                    kunmap(bvec.bv_page);
                    goto io_error;
            }
            kunmap(bvec.bv_page);
            pData += bvec.bv_len;
        }
        __blk_end_request_all(rq, 0);
    }
io_error:
    return;
}
2. make_request version
static blk_qc_t my_make_request(struct request_queue *q, struct bio *bio)
{
	...
 	bio_for_each_segment(bvec, bio, iter) {
        pBuffer = kmap(bvec.bv_page) + bvec.bv_offset;
        switch(bio_data_dir(bio))
        {
            case READ:
                memcpy(pBuffer, pData, bvec.bv_len);
                flush_dcache_page(bvec.bv_page);
                break;
            case WRITE:
                flush_dcache_page(bvec.bv_page);
                memcpy(pData, pBuffer, bvec.bv_len);
                break;
            default:
                kunmap(bvec.bv_page);
                goto io_error;
        }
        kunmap(bvec.bv_page);
        pData += bvec.bv_len;
    }
	...
}
3. Makefile
obj-m += block_driver_make_request.o
obj-m += block_driver_request.o

all:
	make -C  /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Demo

After compile the modules, there will be block_driver_make_request.ko and block_driver_request.ko, these two kernel module would have same behavior.

#you would see /dev/sun_block is created after insmod
my-machine$ sudo insmod block_driver_make_request.ko

#you can use mkfs to make a filesystem
my-machine$ sudo mkfs.ext4 /dev/sun_block
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 32768 1k blocks and 8192 inodes
Filesystem UUID: 5f64e6ee-3ed1-4807-a81f-d00063f0466b
Superblock backups stored on blocks: 
	8193, 24577

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

#can mount the ramdisk
my-machine$  sudo mount /dev/sun_block /mnt
my-machine$  ls /mnt
lost+found

References

Revision

  1. Make a draft version of block device driver - 2019.4.3
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
S7A驱动,7.20版本, Version history S7A OPC server and FIX driver for Siemens S7/S5 communication via Ethernet TCP/IP, MPI or Profibus Version 7.20 Date: 26.02.2007 Version history ================================================================================================================== Build 224 New Functions: Solved problems: - The setup program created a wrong e-doc link in Windows start menu. Now the proper link to S7A.CHM will be installed - From the S7A power tool it wasn't possible to open the online help file. Now it can be opened and also the context-sensitive help works properly. - When the signal conditioning function "S&M" was used for a byte value, the driver wrote wrong values to the PLC. Build 223 : New Functions: - The number of supported NetLinks has been increased from 4 to 64 - Communication error messages will be now displayed in the alarm history of iFIX. This helps to detect, trace and solve communication issues. - Support for MATRIX licence key added. This key does not require a special key driver. It simply needs a PC and a windows version which supports USB ports. - When using the driver in conjunction with NetLink adapter, the licensing now can take place by a license code in the NetLink. In this case a separate licence key (dongle) is not needed. Note: If the connection to the NetLink is disturbed, the driver starts in demo mode, because it can't read out the licence code. If afterwards the connection to the Netlink can be established, the driver automatically changes from demo mode to the licenced mode as long as the demo time has not yet expired. - Support for S7-200 with CP 243-1 was added. Solved problems: - Passing of invalid OPC Item IDs caused a memory leak of the driver's global memory. After the global memory was exhausted, the driver crashed. - Writing of string values failed when using hardware options NULLTERM or SPACEFILL - Wrong OPC timestamp occured when driver was running in NIO Simulation Mode - The driver could crash when the driver was stopped (either by hand or when the demo time was expired) and in the same moment the NetLink connection was disturbed. - Improvements on the seamless switching between primary and backup devices and vice versa. - The passing of invalid OPC Item IDs caused a memory leak in the driver's global memory. After the global memory was exhausted, the driver crashed. - The writing of strings failed when using the hardware options NULLTERM or SPACEFILL Build 222 : New Functions: - The driver can now be registered as a service with the local system account as the log-on account. For more information see the document "S7A_as_Service.PDF" on the installation CD . - The driver now switches "seamless" between primary and backup device and vice versa. Solved problems: - The field "Default Gateway" has been added to the NetLink's configuration property page - The string write from the OPC Server sometimes failed . This bug has been fixed - After driver uninstall, not all of the S7A-related registry entries were deleted. Now the registry will be completely cleaned from S7A registry entries after uninstall. - The Netlink module generated trace messages to debug window. These trace outputs has been removed. Build 221 : New Functions: - The information field "Runtime Mode" has been added to the system statistic display. This shows whether the driver is running in the demo mode or in the licenced mode (with a valid key). - New control tag: "!RuntimeMode:S7A". A digital (i.e. DI) or analog (i.e. AI) block with the I/O address "!RuntimeMode:S7A" delivers the value 0 (in the F_CV property), when the driver is running in the demo mode, or the value 1, when the driver has found a valid key, and therefore is licenced. This function is also available via the OPC server interface. The same item-ID address format has to be used as with the tag-I/O address, thus "!RuntimeMode:S7A" - The information field "Device in use" has been added to the device statistic display. This shows which device (primary or backup-device) is currently active. This state can also be requested via the "!switch" control tag. A digital (i.e. DI) or analog (i.e. AI) block with the I/O address "!switch:<DeviceName> delivers the value 0, when the primary device is active and the value 1 when the backup device is active. For the place holder <DeviceName> in the I/O address the logical name of the driver device, which is requested, must be entered . Example: "!switch:D11" delivers the state of the driver device with the name "D11". This function is also available via the OPC server interface. The same address format has to be used for the tag-I/O address as for the item-ID, thus "!switch:<DeviceName>" - At the channel parameter dialog for the communicatiomn way "S7 TCP/IP" and "MPI/PB CIF", the combo box "Conn.Type" has been added, which now enables the selection of the connection types "PG", "OP" and "other". Until now, a PG connection was used. - In the device dialog of the communication way "MPI/PB CIF", the input fields "Rack:" and "slot no. of CPU" have been added. This extension now allows the connection to "external" Profibus- CPs (CP 342/443-5 or 343/443-5). The Profibus station address of the Profibus CP is stated in the MPI/PB address field. The rack and slot number of the S7-CPU must be stated in the corresponding fields. Please make sure that slot number of the CPU is entered and not of the Profibus-CP!! - The driver now supports the different date and time data types of the S7 PLC. See Topic "Hardware Options for OPC String and TX-Blocks to support S7 date and time data types" in the S7A online help for detailed information. Build 220 : Solved problems: - The own address of CIF50 MPI/PB communication way was limited to 31. Now the limit is 126. - Bug-fix in PG-PC Interface (CP5611) communication way. Device could be disabled from polling, after CP5611 sent a specific sequence of communication errors. Build 219 : Solved problems: Improvements and new functions: - New Parameter "Max Gap (Bytes)" on Setup parameter property page "Advanced". This parameter defines the maximum address gap between an existing and a new block at which the driver automatically appends the new block to the existing. If the address gap is greater, then the driver creates a new data block. This functionality is active, when the data block auto create option is set on. - New Radio Button selection "Show Window" on Setup parameter property page "Advanced" The driver automatically opens its window which shows trace log messages useful for trouble shooting, when the "Yes" Radio button is on. - New HTML Help Build 218 : Solved problems: - Problems with datablocks which have a length between 180 and 200 bytes. - Unsufficient exception handling in S7AMemory.Dll caused blocking of driver and all other clients (WSACTASK, Workspace, etc.) which reads data from the driver. - Error in MIX Read function could cause blocking of data blocks Build 217 : Solved problems: - In configurations with data blocks which have a primary rate of zero (as fast as possible), it sometimes happened that write requests were "stuck" in the write queue. - Sporadic locks of data blocks after the driver was switched from the primary device to the backup device Improvements and new functions: - Improved error and timeout handling on communication faults. The reply timeout on the device configuration page can no longer be configured. Instead it will be derived from the TCP/IP timeout value, configured on the channel configuration page. The value (in seconds) of reply timeout always is 1 second higher than the TCP/IP timeout. This ensures, that the logical read/write request (time-limited by reply timeout value) will not be cancelled (by timeout) before the physical request (time-limited by TCP/IP timeout value) is finished regulary or through the timeout. - The NIO Simulation mode has been expanded. If it is set "ON" the polling of data blocks will be disabled, due to which no communication errors will arise, as long as a PLC hardware is not connected to the driver. In this mode the iFix data base blocks reads the value of zero or respectively, the last value written to the driver`s output data area. - "!SyncPoll" and "!SyncSend" have been added to allow e.g. an EDA application to read/write a data block synchronously Build 216 : Solved problems: (06.06.05) - Reset of statistic counters failed Build 215 : Solved problems: (31.05.05) - An error in the OLE interface methods ReadValue ()and WriteValue() was corrected. These functions can now be used for example,within the Excel program, to access data block values. - Datablocks stopped polling after an 'unknown error' was returned by CP5611 Build 214 : Solved problems: - Syncronous reads/writes from concurrent OPC clients now work properly New function: - Performance has been improved, especially in configuration with a lot of short data blocks. - system, channel, driver and data block static display has been extended Build 213 : Solved problems: - No reconnect after the MPI/Profibus connection between CP5611 and the PLC was aborted. - S7ADRV.EXE could crash on Multi Processor Systems or Systems with Hyperthreading when error messages (e.g. "Unable to connect to MPI station") were put to driver's log window from different threads concurrently. Build 212 : Solved problems: - The AGLink error code -1268 (Unknown error message of the PLC) caused a blocking of the device. Now the device will be closed and re-opened to recover the error. - under very seldom conditions a AGLink error caused a crash of S7ADRV.EXE Build 211 : Solved problems: - Setup of TCP/IP parameters failed with error -510. Problem has been solved. - Problems in configurations with more than 8 devices within a channel have been solved - Import of CSV file from S7A Version 7.16 failed - Failed to read the AG State - Configuration of a backup IP address caused a driver crash when it tried to switch from primary to backup device Build 210 : New functions: - Communication way MPI/Profibus using Siemens CPs (CP5611, 5613) added - Communication way MPI/Profibus using Hilscher CIF50 PB added - Communication to "old" S5 series via TCP/IP added - The old Sentinel Keys will not supported any longer - Check Box "Disable comm alarming" in datablock configuration allows to suppress the COMM alarms of Tags which addresses a driver datablock which is in communication error state. - Now the OPC server is OPC DA 2.05 complient Build 210 : Solved problems: - Under Windows XP the driver crashed when the network cable was not connected to ethernet card and the driver started. - A communication error on a single device caused comm errors on all other devices of the channel Build 201 : Solved problems: - CSV Import/export works now even for the new communication ways. Build 200 : Solved problems: - Handle leakage when using asynchron read mode of OPC server. This problem was fixed by migration to OPC server toolkit version 7.20 New functions: - The driver now supports additional communication ways (serial adapter, NetLink adapter and Siemens CPs (eg. CP5611). It's no longer a pure TCP/IP driver but a general driver for Siemens S7 which allows to connect via TCP/IP, MPI bus or Profibus using different interface hardware (CPs). Build 128 : Solved problems: - In big configurations with a lot of data blocks when a data block has been written it took too long until this data block was read back. Thus between the write and the read the clients (OPC or FIX) read the old data. Now after a write the driver reads the data block priorized. Build 127 : Solved problems: - The addressing range for PLC's input area and output area has been extended from 0..255 bytes to 0..4095 bytes. Build 126 : Solved problems: - Errors in manual and automatic block write functions has been fixed Build 125 : Solved problems: - Very fast consecutive analog writes to the same data block caused a crash of the S7ADRV.EXE process. This problem has been solved. Build 124 : Solved problems: - Different communication problems has been solved. - Design of message passing to driver window has changed to prevent the driver dead locks which occored under a very seldom conditions. Build 123 : Solved problems: - Changing of the IP-Address while the driver was running had no effect. This problem has been solved. Build 122 : New functions: - Now the devices within a channel processing in parallel mode - Added "Bytes per Second" to device and channel statistics - Logging of read/write requests/responses into a log file is now configurable for individual data blocks. File logging can basically be switched on/off at register page "advanced" in power tool's setup screen. - This version is already prepared to support the S7T loadable database block which will allow to work with the S7 TIME and TIME_OF_DAY data types in iFIX database. - Shared memory management has been changed to fix problems with large configurations and multi processor systems. Solved problems: - In previous versions the S7 rack number had no effect. Now it will be mapped into the right bit positions of the "called TSAP" field when opening the ISO connection within the TCP connection. - An error in output simulations mode was fixed. - An error in auto creation of data blocks was fixed. Build 121 : Solved problems: - When the slot and rack number in the device setings has been changed, the new values wasn't used when the connection has been re-established. Now the change of these parameters take place immediately. Fixed wrong display of Transmitted and Received counters of mission control's driver statistics Build 120 : Solved problems: - The OPC Server now supports read/write of Control-Tags (eg. !Send or !PollRate). Address syntax is equal to Tag I/O Address within FIX-Database. - Driver doesn't work when a channel with 8 devices was configured Build 119 : Solved problems: - Timeout value of channel template was not stored, thus it had no effect when a new channel was added. - IP-Address of device template was not stored, thus it had no effect when a new device was added. - To avoid duplicate Connection Numbers in Driver Device config, now these Connection Numbers are assigned automatically. The "Connection No" Field in Powertool's device configuration dialog is no longer enabled for input but for displaying the assigned Connection Number. - The driver devices are now limited to 8 per channel. - When running S7A driver on W2K without hardlock key (Sentinel or HASP) the Power Tool displayed an exception message box and the driver didn't start in demo mode. This problem has been solved. Build 118 : New function: - Additionaly to the Rainbow Sentinel Key the driver now supports new Aladdin HASP Key. It detects either Sentinel or HASP Key. Solved problems: - The OPC Server now supports String addresses Build 117 : Solved problems: - Now the Input Data Area of S7 can be read. That was not possible in build version 115 and 116. - The I/O address in data base builder now accepts inputs of adresses without blank between data area identifier and adress index (e.g. D11:Q1.7 or D11:I10.0). - Under a certain condidtion the S7ADrv process runs into a deadlock situation This problem has been solved. Build 116 : Solved problems: - Now the switching between primary and backup device can be configured and used. If the communication to the primary device fails, the driver automatically switches to the device configured as backup device. If the connection to the backup device fails, it switches back to the primary device. The switching even can be done by "hand" using a DI Block with I/O address "!switch:<Device name>. A F_CV value of 0 means primary device is active, F_CV value 1 means backup device is active. To change the active device just assign the corresponding value to blocks F_CV property. Build 115 : Solved problems: none New functions: - To make troubleshooting easier, the driver now allowes to log messages to a log file. To enable file logging, set the following registry key value to 1: "HKLM\Software\Intellution\Drivers\S7A\DriverDefaults\WriteLogToFile" By default this value is set to 0 which disables the file logging. The log file is named S7ADrv.log and located in the drivers default config file path. All messages dispatched to the driver server window will be logged in the file as well. Caution: The log file will "not" be deleted and re-created when driver starts. It's in the users responsibility to watch the size of the log file. If you enable the dispatching of debug level 1 to 3 messages, the log file can become a huge size in a short time!! Build 114 : Solved problems: - If SAC writes faster to the driver's image table than the driver can write to the PLC, after a while the write queue filled up to 100%. This version of the driver no longer queues write requests to PLC addresses which already in the queue, but uses the already queued request by just replacing the old write value by the new value. - In configurations with more than 1 channel, the driver sometimes crashed since This problem has been solved. - The Send and Receive counts in mission control was swapped. New functions: - Driver now runs with dongle RN-4BDNBH-B (S7A) and RN-4CKEBH-B (S7A+S7B) Build 113 : Solved problems: - Error in S7AMemory.dll caused problem in applications with very large configurations (where the shared memory "S7A_InputArea" exceeded 64k). The data type information stored in the Input Area was overwritten to WORD. Thus the SAC Task interpreted the block values always as an integer no matter what data type was set for the data block in power tool. New functions: - none Build 112 : Solved problems: - CSV File import now works fine - When choosed S7M 1.x compatible address syntax, the data type combo box was been set to a data type other that saved before. New functions: - The S7-TIME format now is supported. Use a TX-blocks and the data type identifier 'T' in the Tag's I/O address to address a double word which contains a value in S7-TIME format (e.g. D11.DB100.DBT 10). Write is also possible. Build 111 : Solved problems: - Sometimes the CPU load raised to 100% when writing values. - Read/write of the last byte of a data block failed. - Block write in manaul or auto mode failed - In data block statistics sreen sometimes "stats error windows" occured because some error codes could not be found in AGLink_Error.txt file. New functions: - none Build 110 : Solved problems: - none New functions: - Added hardware options NULLTERM and SPACEFILL to control string write. Build 109 : Solved problems: - Sometimes driver hangs after communication failed. Occured when a lot of data blocks with a very short poll time has been configured and processed. New functions: - none
Linux Device Driver (3edtion)原版 1. An Introduction to Device Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 The Role of the Device Driver 2 Splitting the Kernel 4 Classes of Devices and Modules 5 Security Issues 8 Version Numbering 10 License Terms 11 Joining the Kernel Development Community 12 Overview of the Book 12 2. Building and Running Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Setting Up Your Test System 15 The Hello World Module 16 Kernel Modules Versus Applications 18 Compiling and Loading 22 The Kernel Symbol Table 28 Preliminaries 30 Initialization and Shutdown 31 Module Parameters 35 Doing It in User Space 37 Quick Reference 39 3. Char Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 The Design of scull 42 Major and Minor Numbers 43 Some Important Data Structures 49 ,ldr3TOC.fm.4587 Page v Thursday, January 20, 2005 9:30 AMvi | Table of Contents Char Device Registration 55 open and release 58 scull’s Memory Usage 60 read and write 63 Playing with the New Devices 70 Quick Reference 70 4. Debugging Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Debugging Support in the Kernel 73 Debugging by Printing 75 Debugging by Querying 82 Debugging by Watching 91 Debugging System Faults 93 Debuggers and Related Tools 99 5. Concurrency and Race Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Pitfalls in scull 107 Concurrency and Its Management 107 Semaphores and Mutexes 109 Completions 114 Spinlocks 116 Locking Traps 121 Alternatives to Locking 123 Quick Reference 130 6. Advanced Char Driver Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 ioctl 135 Blocking I/O 147 poll and select 163 Asynchronous Notification 169 Seeking a Device 171 Access Control on a Device File 173 Quick Reference 179

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值