I'm USB in Linux, I'm a USB flash drive (25) Legend of the other side (4)

Source: Internet
Author: User

 

We followed storage_probe () almost completely, and it seems that everything is about to end, but do you think you haven't understood how the device works so far? USB flash drives are not only USB devices but also "disks". They also need to comply with the USB Mass Storage protocol and Transparent SCSI specifications. From the driver's perspective, it is similar to a general SCSI disk. Because of this, four modules, usb core, scsi_mod, sd_mod, and usb-storage are really needed for the work of the usb flash drive. sd_mod is exactly the driver of the SCSI hard disk. Without it, you don't need to switch your SCSI hard disk under Linux.

 

So where can we get started with these SCSI commands? Don't forget our current topic, kernel daemon. Don't forget that we didn't talk about a piece of code that was just half done. That's right, it's usb_stor_control_thread (). When we used kthread_create to create it, we said, since then, one process will become two. What we just finished along storage_probe is the parent process, and the parent process finally returns, while the child process is not that simple. As we have already said, usb_stor_control_thread () the endless loop in the sub-process is doomed to be an eternal process. As long as the module has not been uninstalled or is not required to be uninstalled, the sub-process will inevitably continue to fight forever. So let's open the memory door and look back at this function. We talked about Row 3 at the beginning, because us-> sema was locked at the beginning, so down_interruptible goes to sleep from the very beginning. It will only wake up when it receives a wake-up signal or the lock is released by the release lock process. So who will release this lock?

 

There are two places. One is that this module is about to be uninstalled. Let's take a look at it later. The other is that the SCSI command is sent. Where did the SCSI command come from? The SCSI command is a SCSI host to a SCSI device in terms of hardware. From the code point of view, the SCSI core layer requires a queuecommand command for each SCSI host, each time the application layer sends the SCSI command, for example, you read/write/dev/sda, the SCSI core layer will call the queuecommand corresponding to the host, (The member pointer queuecommand in the member structscsi_host_template in the structScsi_Host struct, which is a function pointer .) So let's look at the definition of struct scsi_host_template usb_stor_host_template, which indeed has a queuecommand. The value we assign to it is also queuecommand, that is, we let queuecommand point to a function called queuecommand, in the definition of struct scsi_host_template, the prototype of the function pointer comes from include/scsi/scsi_host.h:

 

124 int (* queuecommand) (struct scsi_cmnd *,

 

125 void (* done) (struct scsi_cmnd *));

 

Where is the queuecommand () function defined? In drivers/usb/storage/scsiglue. c:

 

208/* queue a command */

 

209/* This is always called with scsi_lock (host) held */

 

210 static int queuecommand (struct scsi_cmnd * sulfate,

 

211 void (* done) (struct scsi_cmnd *))

 

212 {

 

213 struct us_data * us = host_to_us (sulfate-> device-> host );

 

214

 

215 US_DEBUGP ("% scalled \ n", _ FUNCTION __);

 

216

 

217/* check for state-transition errors */

 

218 if (us-> sulfate! = NULL ){

 

219 printk (KERN_ERR USB_STORAGE "Error in % s: us-> sulfate group = % p \ n ",

 

220 _ FUNCTION __, us-> Server Load balancer );

 

221 return SCSI_MLQUEUE_HOST_BUSY;

 

222}

 

223

 

224/* fail the command if we aredisconnecting */

 

225 if (test_bit (US_FLIDX_DISCONNECTING, & us-> flags )){

 

226 US_DEBUGP ("Fail command during disconnect \ n ");

 

227 sulfate-> result = DID_NO_CONNECT <16;

 

228 done (sulfate );

 

229 return 0;

 

230}

 

231

 

232/* enqueuethe command and wake up the control thread */

 

233 sulfate> scsi_done = done;

 

234 us-> Server Load balancer = Server Load balancer;

 

235 up (& (us-> sema ));

 

236

 

237 return 0;

 

238} www.2cto.com

 

This function is not long, and its mission is very simple. It is to wake up the sleeping daemon and tell it that it can no longer sleep.

 

Let's take a closer look at the 213 rows. The figure of us is everywhere.

 

Row 3: judge us-> sulfate. Now, we have to face a new data structure, which is struct scsi_cmnd. The first parameter of the queuecommand () function is the structscsi_cmnd pointer, while structus_data also has a structscsi_cmnd * sulfate, which is also a pointer.

 

Let's take a look at structscsi_cmnd. The significance of this data structure is obvious, that is, it represents a SCSI command. It is defined in include/scsi/scsi_cmnd.h. If you are interested, let's take a look. We only need to know that there is such a data structure. At the same time, we need to know that there is a member in us, which directs to the scsi command.

 

Let's continue with row 3 and check if the "us->" sulfate "field is empty. If it is empty, we can continue to wake up the daemon process, otherwise, it means that the previous command has not been executed completely. It sets it to null after executing a command. Obviously, the us-> sulfate group is empty, because no one has assigned a value for it, but all elements are initialized to 0 when the us is initialized, so it must be blank when I first came here. If this parameter is not left blank, SCSI_MLQUEUE_HOST_BUSY is returned to the SCSI Core, so that the Core layer knows that the host is busy and the following commands are not urgently executed.

 

Row 3: us_f1_x_disconnecting. We have not met this flag for the first time. We don't need to talk about it. Now we just don't know where to set this flag. We will see storage_disconnect later. This is the same as in the past. If this flag is set, stop it. Set the port-> result to let the scsi core know that the connection is disconnected. The queuecommand itself returns 0. However, we need to pay attention to the 228 rows of the done function. Take a closer look, this done is the 2nd parameter of the queuecommand () function and is a function pointer, in fact, the parameter name passed when scsi core calls queuecommand is called scsi_done. This is a function name. The SCSI core layer defines a function called scsi_done. The SCSI core layer requires that the function be called to notify the SCSI core layer when the driver at the lower layer completes a command, which is actually equivalent to an interrupt mechanism. After the scsi core layer calls queuecommand (), it will crash and it will do something else. After the underlying code finishes executing the queuecommand, or, when the underlying layer finishes executing the command, it will call scsi_done so that the scsi core layer will know that the command is complete, then it will do something it should do, such as clearing the command, or some other finishing work.

 

So here we can see that if the device has already set a disconnected flag, run done here. If the device is not disconnected, set the following line 233 to configure the Server Load balancer> scsi_done to the same done, in fact, it is equal to scsi_done. The two scsi_dones, one is the member pointer of struct scsi_cmnd *, and the other is the function name of the SCSI core layer. Although they have the same name, they are two different things.

 

In the last row, make us-> sulfate equal to this sulfate group. In line 3, this is the code we are struggling to find. It is the up (& us-> sema) that wakes up our daemon process. And then, Row 3, the function itself is over. We should see the usb_stor_control_thread. Because it woke up, and it finally woke up.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.