Re: Proc read function and long output

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thursday 06 May 2004 08:21, Danilo Reinhardt wrote:
> Hi,
>
> I has the following problem with the proc filesystem/read function.
>
> I know i can only write some amount of data at once to a proc
> "listener", but i have to write more data as there is space
> available.

You are not taking the offset 'off' into account.  Lets say you have 
5000 bytes of data you want to output via your /proc file.  Someone 
does a 'cat /proc/your_file'.  Also assume the cat program does a read 
of 5000 for this example.   This is what will happen.

1) proc_read_tis() is called:   off==0  count==3072
   You need to return the first 'count' bytes of your data in 'page'
2) proc_read_tis() is called:   off==3072 count=3072
   You need to return bytes 3072 through 6144 of your data in 'page'
3) proc_read_tis() is called:   off==6144 count=3072
   You need to return bytes 6144 through 4999 of your data in 'page'
   and set *eof to 1

In each of these cases you can put less data in the buffer and adjust 
the return value as necessary.  Your routine will then get called more 
often.  Also you can use 'start' if the very beginning of the buffer is 
prior to 'off'.  See below

> The example at bottom is non working, just for demonstration. At the
> marked line i check if there is space left and snprintf in it... if
> not, i dont write more ;) . But how can i write more data? My text is
> cut off somewhere in the middle.... not good :(

What I have been doing, is that every so often, e.g. once per loop 
itteration often works, I check how much I have written.  If I have not
reached the 'off' position, I dump what I have generated so far and
start at the beginning of the buffer.  e.g.

   for (....) {
	len += sprintf(page+len, "blah blah");

	// 'begin' is the offset into the /proc file corresponding to the
	// start of the buffer.   'len' is how full the buffer (page) is
	pos = begin + len;     // pos is file offset of last byte in buffer
	if (pos < off)  { 
		len = 0;  		// We havn't hit offset yet, start over
		begin = pos;
	} 
	if (pos > off + count)  // We passed end of read request
		goto done;  
   }

and at the end of the routine

   *eof = 1;
   done:
	*start = page + (off - begin);
  	len -= (off - begin);
  	if (len > count)
  		len = count;
 	if (len < 0)
  	 	len = 0;
  	return len;


> This is my code right now:
>
>
> int proc_read_tis(char *page, char **start,
> 					off_t off, int count,
> 					int *eof, void *data) {
> 	int len;
> 	char* out = page;
> 	int idx;
> 	int tcode;
>
> 	out += snprintf(blablabla);
>
> 	for (idx=0;idx<MAX_COUNT*2;idx++) {
> 		out += snprintf(blabla);
> 		for (tcode=0;tcode<16;tcode++) {
> 			if (TCODE_NAMES[tcode]!=NULL) {
>
> /*******************************
> -> PROBLEM HERE, no more space available
> ********************************/
> 		if (count - (out-page)>0) {
> 			out += snprintf(out,count - (out-page),"blablabla....");
> 					}
> 				}
> 			}
> 		}
> 	}
>
>
> 	len = out - page - off;
> 	if (len < count) {
> 		*eof = 1;
> 		if (len <= 0)
> 			return 0;
> 	} else {
> 		len = count;
> 	}
> 	*start = page + off;
> 	return len;
> }


--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux