/proc/file read drops data

Hi , I'm using blooking read call to get some asyn. event from kerne space, as some one suggested previously.

I have tried to use charater driver and /proc files system. The one with c driver seems works fine. I got some problem with /proc/ when the application tries read data.

See my proc_read function bellow. This function will be waked up by interrupt service routine. It appears that appcation has problem with consecutive reads. First ready gets the same number of bytes, after that I can see the folowing function return number of bytes, while the user application's read returns always 0.

The same piece code is used in a charactor driver's read function, that one works OK.

Any suggestions?

static int proc_read_foo(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; if (data_ready) { interruptibe_sleep_on(wait_queue); } memcpy(page, dada_buf, MAX_BUF_LEN); data_ready=0;

return MAX_BUF_LEN; }

Reply to
ask8y
Loading thread data ...

Some typo. post again

I'm using blooking read call to get some asyn. event from kerne space, as some one suggested previously.

I have tried to use charater driver and /proc files system. The one with c driver seems works fine. I got some problem with /proc/ when the application tries read data.

See my proc_read function bellow. This function will be waked up by interrupt service routine. It appears that appcation has problem with consecutive reads. First ready gets the same number of bytes, after that I can see the folowing function return number of bytes, while the user application's read returns always 0.

The same piece code is used in a charactor driver's read function, that one works OK.

Any suggestions?

static int proc_read_foo(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; if (!data_ready) { interruptibe_sleep_on(wait_que=ADue); } memcpy(page, dada_buf, MAX_BUF_LEN); data_ready=3D0;=20

return MAX_BUF_LEN;=20 }

Reply to
ask8y

One thing that stands out is the use of interruptible_sleep_on() which has a race condition associated with it. Look on google; the suggested replacement is wait_event_interruptible().

There's also a discussion in the 2nd edition of Linux Device Drivers about this, online at:

formatting link

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP       
Microsoft: The Standard Oil Company of the 21st century
Reply to
Simon Clubley

behavior is the same, if change it to wait_event_interruptible(). If I tale trhe sleep part completely, it returns correctly the number of bytes. However I want to use the blocking feature.

Reply to
ask

On the second read() is the read handler actually completing ? Try putting printk()'s into the handler and seeing if the read ever gets past the memcpy(). Also, have you checked for any buffer overflow issues in your driver ?

Can you post the actual code (without retyping it) of the read handler, the code around the point in the interrupt handler when you wake up the read handler, and the code around the application level read() ? Someone may see the problem if presented with more code.

BTW, it's not directly related to your current problem, but you are supposed to use copy_to_user() and copy_from_user() when moving data between user and kernel space. This is in case any of the user's buffer has been paged out. This is discussed in Chapter 3 of the LDD manual.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP       
Microsoft: The Standard Oil Company of the 21st century
Reply to
Simon Clubley

Following id the code. After load, /proc/sample si created. mknod /dev/sample c 230 0

To do cat /proc/sample and /dev/sample to observe the difference.

Do echo > /dev/sample to issue an event.

#define MODULE #include #include #include #include

#include

/*length of one entry*/ #define ALARM_REPORT_LEN (1

Reply to
ask

You could remove define SLEEP to see the difference as well.

Reply to
ask

I've had a quick look at your code and got it (apparently) working on Redhat 7.2 (a 2.4 series kernel).

If you modify your sample_proc_read to dump the values of the passed arguments, you will see that offset increments on each call.

I've never created pseudo devices in /proc before, but it looks like you are expected to write your data into buf at the offset given in offset, set start to the start address of this new data in buf, and set eof to 1.

When I modified your code to do this, it appears to work ok, emitting one instance of your test string for each time that I issue the echo command.

I further modified the sample_proc_read routine to return a length of zero (in order to indicate end of file) when the offset got to 256 bytes. This correctly resulted in the "cat /proc/sample" command terminating when this offset was reached.

Some notes:

1) Be careful not to write past the end of the passed buffer

2) You are using MOD_INC_USE_COUNT and not decrementing it, but instead calling MOD_INC_USE_COUNT again. This means that you can't unload your driver after use.

3) You are registering and deregistering the device using different names. This means that you can't reload your driver again.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP       
Microsoft: The Standard Oil Company of the 21st century
Reply to
Simon Clubley

Hi Thnaks for your reply. Did notice, if you do do echo first for a couple of times, and then do cat /proc/sample, the cat does not return what it read immediately, and do another read, until, you do another echo, it return all reports.

While if you try with /dev/sample, it always returns imediately.

Another thing is that, I want cat block there, and never return. It I update continuousely the offset, event it will grow across page boundaries, and I am not if they pages ever get released.

Nice talk.

Reply to
ask

Nice talk with you.

The original thought was to repeatly to use the same page. It woks OK like you suggested to update "start" and put data into "buf+offset". As I understand from LDD book, the kernel use pages to get my data, if I keep updating start, it would think my file is of infinit long, and it would keep all those pages, I dont know if kernel release them all keep them until the proc_read return a 0. Overtime it ocvcupies a lot of resource.

Ideally, I would like "cat" or any application thinks that the file still has data to come at any time, but just use one page, not more.

I think at this point, I am not sure, if I keep updating the offset, if it grow into mutiple pages, can old pages released or still kept.

If I use /dev/sample, I dont have any problem, as data copied from kernel to uaer space by the driver code.

Reply to
ask

You can do as I suggested, and use printk to display the arguments passed to your proc read routine. You may see that the offset returns to zero, but with the same buffer address after more than a page of data has been passed back to the caller.

If it's doesn't (cat may issue large read()'s), then write a small program with a static buffer, say 1024 bytes long, that reads /proc/sample and see what values get passed to your driver's proc read routine. Focus on the buffer address, count and offset values.

The data that you pass back in your proc read routine still has to make it back to user space. If it's buffered by the kernel, instead of the address of the user level buffer been passed to your routine directly, (and I haven't checked the source to see what happens) the buffer may be released once the user level read() has been satisfied.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP       
Microsoft: The Standard Oil Company of the 21st century
Reply to
Simon Clubley

I observe that the offset keeps going up never goes back. I even try after offset > 1024, return a 0, and put *start to buf again. Of cause it terminate "cat", when offset gets 1064 for example. In a small app, I keep calling read, the offset will be always the very last value, 1064. I guess the kernel will continue try the same offset until a close happens.

Reply to
ask

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.